Deploy de app Angular/React para o S3 via GitHub Actions
Tags: angular, react, s3, devops
Published: 2023-03-17 12:00:00

Há um tempo atrás eu escrevi [esse post](https://dev.to/aws-builders/como-criar-e-publicar-uma-aplicacao-angular-no-amazon-s3-49d8) sobre como criar e publicar uma aplicação Angular no S3. Como ambos os frameworks usam a pasta dist, basta seguir os mesmos passos no React.

Agora, nós vamos usar o GitHub Actions pra automatizar o nosso deploy e atualizar o ambiente automaticamente a cada commit na branch principal.

E se você chegou até aqui mas ainda não entendeu muito bem porque publicar uma SPA no S3 ao invés de um nginx ou apache da vida, a resposta é simples: **é tudo HTML, CSS e JS**. Uma SPA tem um monte de JS incorporado, regras de interface, libs, etc. mas no fim disso tudo o código é executado no browser, então a gente só precisa de um servidor de arquivos pra fazer a mágica acontecer.

## Repo
Dessa vez vamos usar um [app react](https://github.com/ricmello/react-s3-app) como exemplo, e se você é do team Angular pode usar [esse repo] (https://github.com/ricmello/angular-s3-app) como base.

## Criando a Action
No seu repositório, vá para a aba actions pra criar o seu primeiro workflow. Digite Node.js na caixa de pesquisa, procure por essa action aqui e clique em **Configure**.

![Node.js Github Action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02fwp1randl4tzq72tvr.png)

> Importante: GitHub Actions é o nome da ferramenta. Dentro dela, nós configuramos os workflows. Um workflow é um conjunto de instruções pra fazer o que você quiser com o seu projeto: rodar testes, buildar a aplicação, fazer o deploy ou tudo isso junto, se você consegue fazer no terminal é possível fazer via Github Actions. Ainda tem uma série de comandos predefinidos pra te ajudar no [marketplace](https://github.com/marketplace?type=actions).

Após clicar em Configure, o GitHub vai gerar um workflow padrão para uma aplicação node:

```yaml
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: 18.x
        cache: 'npm'
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test
```

Explicando o arquivo acima, ele é executado tanto em pushes quanto PRs para a branch main. Roda no ubuntu e executará nas versões 14, 16 e 18 do node. Como a gente não precisa suportar várias versões, eu vou fixar na versão 18.x. Essa é a parte de configuração do workflow.

Nas steps, que são as etapas, o `actions/checkout` baixa o repositório, enquanto o `setup-node` instala o nodejs. Com o node instalado, rodamos o `npm ci` pra [instalar as dependências](https://dev.to/ricmello/npm-install-vs-npm-ci-qual-utilizar-ce9), depois o build e os testes. Como a nossa aplicação não tem testes, eu vou remover essa última linha.

A essa altura, o seu arquivo deve estar assim:

```yaml
name: Deploy React app to S3

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build-and-deploy:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 18.x
      uses: actions/setup-node@v3
      with:
        node-version: 18.x
        cache: 'npm'
    - run: npm ci
    - run: npm run build

```

Agora que já temos o script de build, é hora de publicar no S3. Eu criei um bucket com o nome de `my-react-s3-app` usando as configurações do [tutorial anterior](https://dev.to/aws-builders/como-criar-e-publicar-uma-aplicacao-angular-no-amazon-s3-49d8). Com o bucket pronto, fica faltando configurar as credenciais da AWS e subir os arquivos.

**Com isso, o meu arquivo final ficou assim:**

```yaml
name: Deploy React app to S3

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 18.x
      uses: actions/setup-node@v3
      with:
        node-version: 18.x
        cache: 'npm'
    - run: npm ci
    - run: npm run build

    - name: Setup AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ secrets.AWS_REGION }}

    - name: Deploy to S3
      run: aws s3 sync dist/ s3://my-react-s3-app
```

A step **Setup AWS credentials** configura o workflow pra usar as credenciais de uma conta que eu criei com permissão no S3. Tanto as credenciais quanto a region do meu app estão em secrets, assim eu não deixo nenhuma informação sensível no repositório. 

Você pode ver como gerar as credenciais [nesse link](https://docs.aws.amazon.com/pt_br/powershell/latest/userguide/pstools-appendix-sign-up.html) e você pode encontrar mais informações sobre as secrets [aqui](https://docs.github.com/en/actions/security-guides/encrypted-secrets). Para criar as secrets basta ir no seu **repositório no github > Settings > Secrets and Variables > Actions**.


E por último, mas não menos importante, a task **Deploy to S3** sobe os arquivos pro nosso bucket. Após fazer o push para o repositório, a aplicação fica disponível automaticamente em [alguns segundos](https://github.com/ricmello/react-s3-app/actions/runs/4443180406). Você pode acessar o meu app [nesse link](https://my-react-s3-app.s3.us-west-2.amazonaws.com/index.html)

![App publicado no S3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kli4yqkrkr1w8a15h5f.png)

É isso! E aí, curtiu? Tem alguma dúvida? Se tiver qualquer coisa que eu possa fazer pra tornar esse artigo melhor, se quiser reclamar, elogiar ou sugerir outro artigo, manda ver nos comentários. Feedbacks são sempre super bem vindos.