Atualizando website estático no Amazon S3 via github actions com uma action personalizada
Tags: aws, githubactions, github, javascript
Published: 2023-05-01 19:07:35

![Logotipo github com a palavra Actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gtz9ms0fcx7yzy6ed94.jpg)
_Tenho como objetivo aqui trazer um pouco do poder do github actions, mas como único escopo. Não serão abordados temas como criação de um website, criação de conta AWS, configuração de um bucket S3 na AWS e criação de credenciais AWS._

**Bora lá? :)**

---

## ACTION
No repositório github do seu site, crie na raiz do projeto a pasta _.github_, e dentro desta pasta uma nova pasta chamada _workflows_:
![Print do github exibindo o caminho: meu-site/.github/workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zaipra15le77bxzd9vh.png)

Agora crie dentro da pasta _.github_ outra pasta com nome _actions_, dentro da pasta _actions_ crie um arquivo com o nome _action.yaml_ (<u>o arquivo precisa se chamar action e ter o formato yaml</u>), este arquivo será a action que será acionada por um workflow para fazer o upload dos arquivos do site. Este arquivo deverá ficar da seguinte forma:

```
name: 'Upload S3'
description: 'esta action envia arquivos para o amazon S3'
inputs:
  bucket:
    description: 'Nome do bucket S3'
    required: true
  region:
    description: 'A região do bucket'
    required: false
    default: 'sa-east-1'
  files:
    description: 'Caminho dos arquivos para upload'
    required: true
runs:
  using: 'node16'
  main: 'main.js'
```

Esta action recebe 3 parâmetros de entrada (_inputs_), o nome do bucket, a region do bucket e o caminho dos arquivos para upload. Logo abaixo dos inputs temos o campo runs que chamará um script _'main.js'_ executado com node versão 16.

Agora vamos criar o script _main.js_ que informamos acima na action, este arquivo deverá ficar dentro da pasta _actions_ e conterá o seguinte código javascript:

```
const core = require('@actions/core');
const exec = require('@actions/exec');

function: run() {
  const bucket = core.getInput('bucket', { required=true });
  const region = core.getInput('region', { required=true });
  const files = core.getInput('files', { required=true });
  
  const uri = `s3://${bucket}`
  exec.exec(`aws s3 sync ${files} ${uri} --region ${region}`)
  
  core.notice('Arquivos enviados com sucesso!')
}

run();
```

Nesse script importamos algumas libs para manipular comandos shell e também obter os inputs informados na action. A função _run()_ lê os inputs da action e em seguida monta a uri do nosso bucket, então é executado o comando para sincronizar os arquivos contidos no caminho informado pelo input _'files'_ com o bucket informado no input _'uri'_.  

&nbsp;
## WORKFLOW
Nossa action está pronta e nosso script de upload também, agora vamos montar o workflow que chamará essa action e enviará os inputs necessários para o upload dos arquivos.

Para isso, crie dentro da pasta _workflow_ um arquivo com o nome de sua preferência no formato _.yaml_, aqui vou chama-lo de _upload.yaml_ e ele terá o seguinte conteúdo:

```
name: Upload

on:
  push:
    branches:
      - main

jobs:
  upload:
    runs-on: ubuntu-latest
    steps:
      - name: Get code
        uses: actions/checkout@v3
      - name: Upload files
        uses: ./.github/actions
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        with:
          bucket: 'my-bucket'
          region: 'sa-east-1'
          files: ./files
```

Esse workflow sera acionado toda vez que houver um push na branch main, definimos isso com o campo _'on'_, para conhecer mais formas de acionar o workflow clique [aqui](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows). 

Na sequência definimos o job _'upload'_ e informamos que ele utilizará o SO _'ubuntu'_ na sua ultima versão, essa imagem de SO já trás pra nós algumas ferramentas importantes como a CLI da AWS que usamos para fazer o upload dos arquivos dentro do nosso script _main.js_. Clique [aqui](https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md) e confira todas as ferramentas que já vem no ubuntu-latest.

Definimos então os steps do job, o primeiro step _'Get code'_ fará o download do nosso repositório, isso é necessário pois este diretório contém a action e os scripts que queremos executar, além de conter os arquivos que queremos enviar para o bucket S3. 

No step seguinte _'Upload files'_ chamamos a nossa action, note que no campo _uses_ estou informando o caminho onde está a nossa action criada, o arquivo _action.yaml_ será detectado automaticamente pelo github. Passamos também os 3 inputs necessários para a action executar, o nome do bucket, a region e o caminho dos arquivos que devem ser enviados ao bucket _(no meu repositório, criei uma pasta chamada files e dentro dela residem os arquivos .html, por isso no input files declarei ./files)_

Passamos também as credenciais da AWS no campo _'env'_ para que o nosso script _'main.js'_ consiga através dessas credenciais enviar os arquivos ao bucket sem nenhum problema de acesso.  

&nbsp;
## CREDENCIAIS AWS
As credenciais devem ser obtidas no console AWS e armazenadas no github na forma de secrets conforme abaixo:

![Tela do github onde se configuram variáveis e segredo para serem usados no projeto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zpj4539lgg9e2s25xl2.png)

> Para criar os secrets conforme imagem acima, basta ir na aba 'Settings' do github e então no menu lateral esquerdo procurar por 'secrets and variables' e escolher a opção 'actions'.

---

### **PRONTO**
Agora nossa action customizada está pronta e sempre que houver um push na branch main, nossos arquivos são enviados para o bucket S3 na AWS.

**Considerações:**
1. O seu bucket S3 deverá estar configurado como um website estático, clique [aqui](https://docs.aws.amazon.com/pt_br/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html) para entender como fazer isso.
2. A action que criamos aqui reside dentro do repositório do próprio website, porém esta action pode ser criada separadamente em um repositório onde apenas ela reside, nesse caso os arquivos da action devem ficar todos na raiz do repositório e não na pasta .github.
3. Este exemplo envia arquivos para um bucket S3, mas abre possibilidades para vários cenários na AWS, como acessar uma EC2, criar um secret no AWS Secrets Manager dentre outros.
4. Este tipo de action customizada só funciona com código javascript que é aceito pelo github, mas caso queira usar outra linguagem como python, java e etc, você deverá usar actions com containers docker.
5. Você pode usar uma action fornecida pela própria AWS para configurar sua credenciais ou outras formas de acesso, veja como clicando [aqui](https://github.com/marketplace/actions/configure-aws-credentials-for-github-actions).

---

## **CONCLUSÃO**
O Github Actions é uma ferramenta poderosíssima e que todo dev precisa conhecer, através dela conseguimos dentro do nosso próprio repositório de código realizar várias tarefas como testes, deploys, validações, checagens personalizadas e etc, vale muito a pena se aprofundar no tema e conhecer cada vez mais, espero que este artigo tenha agregado algum conhecimento a você, confira a documentação oficial das actions clicando [aqui](https://docs.github.com/pt/actions).

Abraços! :)