Website estático com S3 e GitHub Actions

Website estático com S3 e GitHub Actions

O objetivo deste artigo é demonstrar ao leitor, dado um website estático, como configurar de forma prática e rápida o processo de deploy utilizando o GitHub Actions.

Antes de entrar no detalhe da configuração do GitHub Actions, precisamos de alguns passos anteriores, como a criação de um website estático e a configuração de um bucket no S3 para receber os arquivos e entregá-los via http request.

Ambiente e Ferramentas

Vamos utilizar o sistema operacional Linux Ubuntu de forma nativa. Se você é um usuário de macOS não terá problemas pois as ferramentas necessárais podem ser utilizadas praticamente de forma nativa entre esses dois sistemas.

Já se você está utilizando o Windows, sugiro fortemente que utilize uma VM (VirtualBox) ou instale o WSL 2 com o Ubuntu ou algum sistema *unix de sua preferência.

Apenas para fins didáticos, vamos utilizar o Hugo Framework para a criação de um website estático simples. No próximo tópico vou passar de forma bastante rápida como criar um website utilizando essa ferramenta. Caso tenha se interessado, dê uma olhada no website do framework para maiores detalhes.

No tópico seguinte, vamos criar uma chave de permissionamento na Amazon Web Services (AWS), além de criar um bucket, definir as permissões e passar pelas configurações necessárias para a entrega do conteúdo do mesmo via http.

Por último, o mais esperado, iremos dentro de um repositório no GitHub criar a action para que sempre que seja feito um commit na branch main, seja disparada uma action a fim de realizar o processo de build e deploy no bucket S3.


Criando o website estático

Instalando o Hugo

Se você ainda não possui o Hugo instalado, pode fazê-lo agora através do comando abaixo. Se você não possui o Brew na sua máquina, dê uma olhada no site oficial:

Criando o website

Execute os seguintes comandos abaixo:


Gerando conteúdo

Após a instalação, vamos criar a primeira página. Para isso execute o comando:

Para ver o seu conteúdo recém gerado, execute o comando hugo server -D e acesse a URL local http://localhost:1313. Você deverá ver um conteúdo parecido com o da imagem abaixo:

Até aqui concluímos o nosso primeiro objetivo que era instalar e criar algum conteúdo estático.

No próximo tópico vamos criar e configurar um bucket no S3.

AWS

O bucket S3 servirá como um servidor web, entregando o conteúdo gerado pelo Hugo.

Neste tópico assumirei que você já possui uma conta na AWS válida.

Iremos abordar os seguintes passos:

  • Criar um bucket S3 no console da AWS;
  • Configurar o bucket para que o conteúdo possa ser acessado via HTTP request;
  • Criar um usuário na AWS que tenha permissão de alterar o conteúdo deste bucket de forma programática.

Criando o bucket

Após fazer o login no console da AWS, na caixa de busca digite S3 e clique no primeiro item.

Clique no botão Create bucket:


Para este exercício, vou listar abaixo as configurações que deverão ser alteradas. Todas as demais sugiro que as deixe como padrão.

  • Bucket name: revelo-website-estatico;
  • AWS Region: us-east-1;
  • Block all public access: desmarque todas as opções em seguida marque a opção que você reconhece que os objetos do bucket estarão acessíveis de forma pública;
  • Clique em Create bucket.

Segue abaixo a sequência de telas:

Bucket name e AWS Region.
Bloqueio de acesso público ao bucket.


Configurando o bucket

Agora que já temos o bucket criado, devemos concluir a configuração para que este tenha acesso público permitido.

Clique no seu bucket e em seguida na aba Permissions:

Siga até o item Bucket policy, clique em edit e insira o seguinte conteúdo:

{

"Version": "2012-10-17",

"Statement": [

{

"Sid": "AddPerm",

"Effect": "Allow",

"Principal": {

"AWS": "*"

},

"Action": "s3:GetObject",

"Resource": "arn:aws:s3:::revelo-website-estatico/*"

}

]

}


Neste JSON, estamos liberando o acesso para que qualquer pessoa consiga obter (GET) o conteúdo do bucket. Note que estou informando o nome do bucket recém criado na entrada Resource. Você deverá informar o nome do bucket que você criou na sua conta AWS.

Após inserido o conteúdo, clique no botão Save changes.

Pronto, seu bucket já está liberado para ser acessado publicamente. Se quiser, faça um teste, faça o upload de um arquivo para este bucket e tente acessar pelo seu browser.

Após definir as permissões, selecione a aba Properties, role a tela até o grupo: Static website hosting e clique em Edit:

Propriedades do bucket.

Selecione a opção Enable, informe um documento padrão index.html e clique em Save changes:

Selecionando a opção de Static Website Hosting.


Após esta liberação para hospedagem de website, você conseguirá ver a URL pública do bucket. Copie e guarde este endereço, pois ele será o endereço que utilizaremos para acessar o nosso website assim que finalizarmos a configuração do GitHub Actions.

URL pública do nosso bucket.

Usuário para inserir conteúdo no bucket

O último passo agora é criar um usuário para inserir o conteúdo gerado pelo Hugo neste bucket.

De volta ao console da AWS, digite na caixa de busca de serviços IAM e clique no primeiro item.


IAM é o acrónimo para Identity and Access Management. Nesta área vamos criar um usuário que tenha permissão para inserir e remover conteúdo do bucket que acabamos de criar.

Idealmente você deve criar um usuário com acesso apenas com os recursos que são necessários, para evitar muitos passos nessa configuração e não perdemos muito tempo, vamos criar um novo usuário com acesso total a todos os buckets.

Após entrar na tela inicial do IAM, siga os passos:

  • Dentro de Access management, clique em Users;
  • Clique em Add Users;
  • Primeiro passo: Dê um nome para este novo usuário, no campo User name defina um nome que tenha alguma relação com o projeto em questão, para o nosso exemplo, vou utilizar revelo_estatico_ghaction_user, clique em Next;
  • Segundo passo: (1) Selecione Attach policies directly, (2) faça uma busca com o texto s3fullaccess, (3) selecione o primeiro item e clique em Next;
  • Terceiro passo: Clique em Create User.
Tela inicial do IAM.
Step 1: User name.
Step 2: Set Permissions.
Step 3: Review and create.

Com o usuário criado, você conseguirá criar a AWS Secret e a AWS Key que serão necessários para conseguir acesso programático aos buckets.

Para isso, localize o seu usuário na lista de usuário de IAM e clique para ver os detalhes do usuário.

Você deverá ver uma tela parecida com a mostrada abaixo. Clique na aba Security credentials e em seguida role a tela até o grupo Access keys clique em Create access key.

Tela com o detalhe do usuário com a aba Security credentials selecionada.

Na tela Access key best practices & alternatives selecione o primeiro item, Command Line Interface (CLI) e selecione o checkbox I understand…, clique em Next, na segunda tela Set description tag deixe em branco e clique em Create access key.

Step 1: Utilização e alternativas para a access key.

Feito isso, no terceiro passo você já terá acesso ao Access key e ao Secret access key, essas duas informações são referentes ao Username e Password para acesso aos seus buckets, respectivamente.

Copie e cole as duas informações em um arquivo texto seguro na sua máquina ou faça o download do .csv.

A secret key não será exibida mais, se você a perder ou se ela for divulgada publicamente, você deverá desabilitar essa access key e gerar uma nova para este mesmo usuário.

Step 3: Access key e Secret access key.

Se quiser testar o acesso aos buckets utilizando este usuário, baixe o CrossFTP ou Cyberduck e configure os dados de acesso.

Github Actions

Depois de passar por todos esses passos na criação de um projeto de website estático e depois da criação e configuração de um bucket na AWS, chegamos finalmente ao tópico central deste artigo, que é automatizar o processo de fazer o deployment e deixar a nova implementação ou conteúdo público, assim que você fizer um commit na branch main do seu repositório.

O GH Actions pode ser dividido em duas partes: Workflows e Actions.

Workflows: São os propósitos que dispararam as ações. Cada workflow pode ter uma ou mais actions. Alguns exemplos de workflows:

  • Sempre que um novo commit for feito em uma branch específica;
  • Sempre que uma tag for criada;
  • Em um determinado horário.

Actions: São as atividades que serão executadas, como por exemplo:

  • Fazer o processo de instalação de dependências;
  • Fazer o processo de build;
  • Fazer o processo de deployment;
  • Enviar uma notificação no Slack.


Este conteúdo deve ser criado obrigatoriamente dentro do diretório .github e no root do seu projeto.

Estrutura do projeto e do diretório do .github.

Workflow

Em nosso projeto criamos apenas um workflow chamado push_run.yaml, que será disparado quando houver um (1) push na branch main.

Declaramos também algumas (2) variáveis de ambiente para nos auxiliar no processo de envio do conteúdo para o nosso bucket.

O processo é composto por (4) três passos:

  1. Checkout do código fonte do nosso repositório juntamente com os submódulos;
  2. Build do projeto Hugo;
  3. Deployment do conteúdo gerado pelo processo de build.

Todo este processo será executado (3) sob uma imagem do Ubuntu versão 22.04.

Veja abaixo o código refletindo todos os pontos acima:

.github/workflows/push_run.yaml.

Actions

O nosso workflow possui 3 actions. A primeira é o processo de checkout, processo de build e processo de deployment. Essas duas últimas foram criadas exclusivamente para o nosso projeto, vamos entrar no detalhe de cada uma delas.

Action: Build

A action de build contém dois passos que são duas execuções em linha de comando, que você pode rodar na sua máquina ou VM.

A primeira delas (1) faz a instalação do Hugo dentro da imagem ubuntu-22.-04 definida no workflow. A segunda linha de comando (2) executa o build do conteúdo do Hugo. Por padrão, este processo gera a saída dentro do diretório ./public do nosso projeto.

Veja a seguir o conteúdo da action de build:

.github/actions/build.action.yaml.

Action: Deploy


Nossa segunda action é responsável por fazer o deploy. O nosso processo de deployment é bastante simples pois apenas envia o conteúdo do diretório ./public (gerado pela Action: Build) para o nosso bucket no S3.

Nesta action criamos um novo elemento que são as variáveis de ambiente. Em nosso workflow.yaml definimos algumas variáveis de ambiente e as estamos utilizando.

Apenas para fins didáticos, a access key e a secret key estão definidas no nosso arquivo de workflow. Idealmente, essas variáveis devem ser armazenadas dentro do projeto do GitHub em Settings> Security> Secrets and variables> Actions.

As variáveis definidas no workflow.yaml estão sendo utilizadas na nossa action através da entrava env. Dentro dessa entrada temos várias definições que fazem uso dos valores definidos no workflow através do uso de ${{ env.VARIAVEL }}.

As definições de env são exports na linha de comando, ou seja as 4 definições são interpretadas pelo container como:

Por este motivo, é possível utilizar o awscli, sem passar nenhum parâmetro de acesso, pois ele já utiliza essas variáveis de ambiente como referência na execução do comando de sync entre o diretório local ./public com o bucket $aws_bucket_name.

Você pode acompanhar toda a execução do workflow através da aba Actions na página do projeto no GitHub.


Passo final

Agora que já temos 1) o projeto criado; 2) bucket s3 que servirá como servidor web e 3) as actions configuradas, basta você baixar o código deste repositório, cria um novo repositório em sua conta do GitHub e fazer um push na branch main.

Depois de fazer seu push na branch main, acesse a URL pública, informada no último passo da criação do bucket S3 e explore o conteúdo.

Conclusão

O processo de deployment por apenas fazer um commit em uma branch é bastante parecido com o processo de deployment utilizado pelo Heroku. A grande diferença aqui é que você possui mais flexibilidade no decorrer do processo e na finalização deste processo.

Em um momento mais avançado, por exemplo, é possível fazer deploy de sistemas inteiros, backend em Kubernetes, frontend em S3, reset de Cloudfront, executar migrações do banco de dados. Praticamente tudo que pode ser executado via linha de comando, pode ser inserido como uma action.

Repositório do projeto: https://github.com/mangar/static_s3_ghactions.

Sucesso!

Referências

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.