Sitio web estático con S3 y GitHub Actions

Sitio web estático con S3 y GitHub Actions

El propósito de este artículo es demostrar cómo configurar el proceso de implementación de una manera práctica y rápida utilizando GitHub Actions.‌‌‌‌Antes de entrar en detalles sobre la configuración de GitHub Actions, necesitamos algunos pasos previos, como crear un sitio web estático y configurar un bucket S3 para recibir archivos y entregarlos a través de una  http request.‌‌

Ambiente y Herramentas

‌‌Vamos a utilizar el sistema operativo Linux Ubuntu de forma nativa. Si eres usuario de macOS, no tendrás ningún problema porque las herramientas necesarias se pueden utilizar de forma prácticamente nativa entre estos dos sistemas.‌‌‌‌Si usas Windows, sugiero emplear una VM (VirtualBox) o instalar WSL 2 con Ubuntu o cualquier sistema *unix de tu elección.‌‌‌‌

Solo con fines didácticos, vamos a utilizar Hugo Framework para crear un sitio web estático simple. En el siguiente tema, repasaré muy rápidamente cómo crear un sitio web con esta herramienta. Si estás interesado/a, echa un vistazo al sitio web del framework para obtener más detalles.‌‌‌‌En el siguiente tema, vamos a crear una clave de permiso en Amazon Web Services (AWS), además de crear un bucket, definir los permisos y realizar las configuraciones necesarias para entregar el contenido a través de http.‌‌‌‌

Finalmente, y lo más esperado, crearemos una acción dentro de un repositorio en GitHub para que cada vez que se realice un commit en el branch main, se active una acción para realizar el proceso de build y deploy en el bucket S3.‌‌‌

‌‌
Crear el website estático


‌‌Instalar Hugo

‌‌Si aún no tienes instalado Hugo, puedes hacerlo ahora usando el siguiente comando. Si no tienes Brew en tu equipo, dale un vistazo al sitio oficial:


Crear el website

‌‌Ejecuta los siguientes comandos:

‌‌

Generar contenido

‌‌Después de la instalación, vamos a crear la primera página. Para hacer esto, ejecuta el comando:

Para ver el contenido recién generado, ejecuta hugo server -D y accede a la URL local http://localhost:1313. Deberías ver contenido similar a la imagen a continuación:

Hasta ahora hemos completado nuestro primer objetivo: instalar y crear contenido estático.‌‌‌‌En el siguiente tema, crearemos y configuraremos un bucket en S3.


‌‌AWS

‌‌El bucket S3 fungirá como servidor web y entregará contenido generado por Hugo.‌‌‌‌En este tema, supondré que ya tienes una cuenta de AWS válida.‌‌‌‌Cubriremos los siguientes pasos:‌‌

  • Crear un bucket S3 en la consola de AWS;
  • Configurar el bucket para que el contenido pueda ser accesado vía HTTP request;
  • Crear un usuario en AWS que tenga permiso de alterar el contenido de este bucket de forma programática.‌‌

Crear el bucket
‌‌

Después de hacer login en la consola de AWS, en la caja de búsqueda inserta S3 y haz clic en el primer ítem.


Selecciona el botón Create bucket:


Para este ejercicio, enumeraré a continuación las configuraciones que deberán cambiarse. Sugiero dejar todo lo demás como predeterminado.

  • Bucket name: revelo-website-estatico;
  • AWS Region: us-east-1;
  • Block all public access: deselecciona todas las opciones y enseguida marca la opción con la que reconoces que los objetos del bucket estarán accesibles de forma pública;
  • Clic en Create bucket.

Aquí verás la secuencia de pantallas:‌                                    

Bucket name e AWS Region.
Bloqueo de acceso público al bucket.

Configurar el bucket‌‌

Ahora que ya tenemos creado el bucket, debemos concluir la configuración para que tenga permitido el acceso público.

Haz clic en tu bucket y luego en la pestaña Permissions:

Sigue hasta el ítem Bucket policy, selecciona edit e inserta lo siguiente:‌

{

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

"Statement": [

{

"Sid": "AddPerm",

"Effect": "Allow",

"Principal": {

"AWS": "*"

},

"Action": "s3:GetObject",

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

}

]

}

En este JSON, liberamos el acceso para que cualquiera obtenga (GET) el contenido del bucket. Nota que informo el nombre del bucket recién creado en la entrada Resource. Deberás indicar el nombre del bucket que creaste en tu cuenta AWS.

Insertado el contenido, clic en el botón Save changes.

¡Listo! Tu bucket ya tiene acceso público. Si quieres, haz una prueba o un upload de un archivo para este bucket e intenta acceder desde tu browser.

Después de definir los permisos, selecciona la pestaña Properties y avanza en la pantalla hasta el grupo Static website hosting. Haz clic en Edit:‌                                        

Propiedades del bucket.


Selecciona la opción Enable, genera un documento padrón index.html y haz clic en Save changes:
‌                                          

Seleccionando la opción de Static Website Hosting.


Tras esta liberación para hospedaje del website, verás la URL pública del bucket. Copia e guarda esta dirección, pues será la utilizada para acceder a nuestro website. De esta forma, finalizamos la configuración de GitHub Actions.‌                                            

URL pública de nuestro bucket.


Usuário para inserir conteúdo no bucket‌‌

El último paso ahora es crear un usuario para insertar el contenido generado por Hugo en este bucket.

De vuelta a la consola de AWS, digita en la caja de búsqueda IAM y elige el primer ítem.‌                                        

IAM es el acrónimo para Identity and Access Management. En esta área crearemos un usuario con permiso para insertar y remover contenido del bucket que acabamos de crear.

Idealmente, debes crear un usuario con acceso apenas con los recursos necesarios. Para evitar muchos pasos en la configuración y perder tempo, crearemos un nuevo usuario con acceso total a todos los buckets.

Luego de entrar en la pantalla inicial de IAM, sigue estos pasos:

  • Dentro de Access management, clic en Users;
  • Clic en Add Users;
  • Primer paso: Da un nombre a este nuevo usuario. En el campo User name, elige un nombre que tenga alguna relación con el proyecto en cuestión. Para nuestro ejemplo, voy a utilizar revelo_estatico_ghaction_user. Haz clic en Next;
  • Segundo paso: (1) Selecciona Attach policies directly, (2) haz una búsqueda con el texto s3fullaccess, (3) selecciona el primer ítem y haz clic en Next;
  • Tercer paso: Clic en Create User.‌‌‌‌
Pantalla inicial de IAM.
Paso 1: User name.
Step 2: Set Permissions.
Step 3: Review and create.

Creado el usuario, podrás generar AWS Secret y AWS Key, necesarios para conseguir acesso programático a los buckets.

Para eso, localiza tu usuario en la lista de IAM y haz clic para ver los detalles del usuario.

Deberías ver una tela parecida a la mostrada abajo. Selecciona la pestaña Security credentials y avanza hasta el grupo Access keys para luego hacer clic en Create access key.

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

En la pantalla Access key best practices & alternatives, selecciona el primer ítem, Command Line Interface (CLI) y elige el checkbox I understand…, clic en Next. En la segunda pantalla, deja en blanco Set description tag y elige Create access key.

Step 1: Uso y opciones para el access key.

Hecho eso, en el tercero paso tendrás acceso al Access key y al Secret access key. Ambos son referentes al Username y Password para acceder a tus buckets, respectivamente.

Copia y pega ambos datos en un archivo de texto seguro en tu equipo o descárgalo como .csv.

Ya no se exhibirá el secret key. Si la pierdes o se divulgó públicamente, deberás deshabilitar esa access key y generar una nueva para este mismo usuario.

Step 3: Access key y Secret access key.

Se quieres probar el acceso a los buckets utilizados por este usuario, descarga CrossFTP o Cyberduck y configura los datos de acceso.

Github Actions

Después de todos estos pasos en la creación de un proyecto de website estático e tras la creación y configuración de un bucket en AWS, llegamos finalmente al tópico central de este artículo: automatizar el proceso de deployment y dejar la nueva implementación o contenido público, así que haz un commit en el branch main de tu repositorio.

GH Actions puede ser dividido en dos partes: Workflows y Actions.

Workflows: Son los propósitos que dispararán las acciones. Cada workflow puede tener una o más actions. Algunos ejemplos de workflows:

  • Siempre que un nuevo commit fuera hecho en una branch específica;
  • Siempre que un tag fuera creado;
  • En un horario determinado.

Actions: Son las actividades que serán ejecutadas, como por exemplo:

  • Hacer el proceso de instalación de dependencias;
  • Hacer el proceso de build;
  • Hacer el proceso de deployment;
  • Enviar una notificación a Slack.


Este contenido debe ser creado obligatoriamente dentro del directorio .github y en el root de tu proyecto.

Estructura del proyecto y del directorio de .github.

Workflow

En nuestro proyecto creamos apenas un workflow llamado push_run.yaml, que será ejecutado cuando hubiera un (1) push en el branch main.

Declaramos también algunas (2) variables de ambiente para auxiliarnos en el proceso de envío de contenido para nuestro bucket.

El proceso está compuesto por (4) tres pasos:

  1. Checkout de código fuente de nuestro repositorio, conjuntamente con los submódulos;
  2. Build del proyecto Hugo;
  3. Deployment del contenido generado por el proceso de build.

Todo será ejecutado (3) sobre una imagen de Ubuntu versión 22.04.

Ve abajo el código con todos los puntos descritos:

.github/workflows/push_run.yaml.

Actions

Nuestro workflow posee 3 actions: proceso de checkout, de build y de deployment. Las dos últimas fueron creadas exclusivamente para este proyecto, así que vamos a entrar en detalle sobre cada una de ellas.

Action: Build

Contiene dos ejecuciones en línea de comando que puedes aplicar en tu equipo o VM.

La primera (1) instala Hugo dentro de la imagen ubuntu-22.-04 definida en el workflow. La segunda (2) ejecuta el build del contenido de Hugo. Por patrón, este proceso genera la salida dentro del directorio ./public de nuestro proyecto.

Así es el contenido del action de build:

.github/actions/build.action.yaml.

Action: Deploy


Nuestra segunda action es responsable de hacer el deploy. Nuestro proceso de deployment es bastante simple, pues apenas envía el contenido del directorio ./public (generado por la Action: Build) para nuestro bucket en S3.

En esta action creamos un nuevo elemento que son las variables de ambiente. En nuestro workflow.yaml definimos algunas variables de ambiente y las estamos utilizando.

Solo para fines didáticos, el access key y el secret key están definidos en nuestro archivo de workflow. Idealmente, esas variables deben ser almacenadas dentro del proyecto de GitHub en Settings> Security> Secrets and variables> Actions.

Las variables definidas en el workflow.yaml son utilizadas en nuestra action a través de env. Dentro de esa entrada tenemos varias definiciones que usan valores definidos en el workflow mediante ${{ env.VARIAVEL }}.

Las definiciones de env son exports en la línea de comando, es decir, las cuatro definiciones son interpretadas por el container como:

Por este motivo, es posible utilizar awscli, sin pasar ningún parámetro de acceso, pues ya utiliza esas variables de ambiente como referencia en la ejecución del comando de sync entre el directorio local ./public y el bucket $aws_bucket_name.

Puedes seguir toda la ejecución del workflow en la pestaña Actions en la página del proyecto en GitHub.

Paso final

Ahora que ya tenemos 1) el proyecto creado; 2) bucket s3 que actuará como servidor web y 3) las actions configuradas, basta descargar el código de este repositorio, crear uno nuevo en tu cuenta de GitHub y hacer un push en la branch main.

Después de hacer tu push en la branch main, accede a la URL pública, informada en el último paso de la creación del bucket S3 y explora el contenido.

Conclusión

El proceso de deployment para hacer un commit en una branch es bastante parecido al de deployment utilizado por Heroku. La grand diferencia aquí es que posees más flexibilidad durante todas las etapas.

En un momento más avanzado, por ejemplo, es posible hacer deploy de sistemas enteros, backend en Kubernetes, frontend en S3, reset de Cloudfront o ejecutar migraciones de bases de datos. Prácticamente todo lo que pode ejecutarse vía líneas de comando, puede insertarse como una action.

Repositorio del proyecto: https://github.com/mangar/static_s3_ghactions.

¡Éxito!

Referencias

💡
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Listopro.

Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.