SetValue.NETSetValue.NET

Azure Static Web App

June 07, 2020

Generic badge

Azure Static Web App

Static Web App es el nuevo servicio PaaS que se ha publicado hace unas semanas en el Portal de Azure. Este servicio permite desplegar automáticamente webs full stack desde un repositorio de GitHub.

Este tipo de aplicaciones habitualmente son construidas con frameworks como React, Vue o Angular, y su resultado son un conjunto de ficheros HTML, JavaScript y CSS, además de las imágenes que componen el sitio.

Ventajas

Fundamentales

En primer lugar, es gratis, decir hosting gratis y Azure en la misma frase no suele ser muy habitual. Por otro, tiene geo-replicación, un servicio de Azure con geo-replicación y gratis tampoco es habitual. Un servicio free con replicación alrededor del mundo para permitir así que la web app sirva los ficheros más rápidamente al usuario que los consume, es algo que me parece increíble.

Por si esto fuera poco, tiene una API integrada que te permite conectar a Azure Functions para poder ampliar la funcionalidad del sitio estático.

Se integra con un repositorio de GitHub, y se actualiza con una Action -autogenerada por el servicio y que puedes personalizar- desencadenada cuando se produce un cambio en el repositorio asociado.

Versiones de Staging que se generan a partir de Pull Requests, lo que permite previsualizar el sitio en un slot antes de publicarlo definitivamente.

Custom Domains, esta funcionalidad en las Web App depende de un Service Plan de pago, aquí se puede poner sin necesidad de pasar por caja.

Reglas de enrutamiento al back-end mediante un fichero routes.json para tener un control total sobre el contenido.

Seguridad

A nivel de seguridad del sitio, certificados SSL gratis. Hoy en día, cualquier sitio web debe llevar su propio certificado, y aunque hay múltiples formas de crear un certificado digital y de automatizar este proceso, siempre es mejor si lo tienes creado por defecto.

Integración con los proveedores de Autenticación de AAD, Facebook, Google, Twitter o GitHub. Y se puede hacer una definición de autorizaciones y roles, con asignación temporal por horas de hasta un máximo de 7 días.

También tiene un modelo de seguridad con un reverse-proxy para cuando llama a APIs, que se puede hacer sin que haya configuración CORS.

Let's go

En el Portal de Azure, creamos un nuevo recurso.

New Static Web App

A continuación, podemos ver la clásica ventana de Overview y de Plans dónde se confirma que es un servicio gratuito.

Overview Static Web App

Overview

Plans Static Web App

Plans

Se configura la creación del servicio estableciendo la suscripción, el grupo de recursos, nombre y la ubicación del Data Center, y establecemos el SKU en Free,actualmente no hay más opción que gratis, en un futuro seguramente cambiará.

Basics Static Web App

Una vez configurado el servicio se realiza la conexión con la cuenta de GitHub para poder seleccionar después el repositorio que se va a conectar al servicio.

Authorize Azure Static Web Apps

Tras la autorización, se selecciona el repositorio y la rama que se va a enlazar con el servicio.

Repo and Azure Static Web Apps

En la sección de Build se define obligatoriamente la ruta del código de la web estática dentro del repo, y alternativamente la ruta dónde se encuentran las Azure Function y si aplica el artefacto resultante de la build de la app.

Paths Azure Static Web Apps

Por último, se crea y comienza el despliegue del sitio estático.

Confirm and Create Azure Static Web Apps

A diferencia de la adquisición de otros servicios de Azure, que se puede realizar desde un terminal (PowerShell, Azure CLI...), éste aún no se puede construir así, además de porque está en preview, probablemente porque requiere la creación de un token de la cuenta de GitHub para poder crear la GitHub Action en el repositorio, y para lograr esta integración hay que realizar una autenticación interactiva.

Nota: Si intentas exportar la plantilla ARM, te da este error "The schema of resource type 'Microsoft.Web/staticSites' is not available. Resources of this type will not be exported to the template".

Inmediatamente después de la adquisición del servicio, si se accede a las Actions del repositorio, se puede ver que está ejecutándose un yaml que ha creado el servicio de forma automática.

GitHub Actions executing

Una vez ejecutada la GitHub Action, al acceder a la ruta del sitio estático, se ve el sitio estático desplegado.

Static Web App deployed

Configuración

Dentro del servicio en el Portal de Azure, a diferencia de otros servicios, se puede establecer muy pocas configuraciones, eso sí, son bastante atípicas comparadas con otros servicios PaaS como las Web App.

Configuration

Permite establecer settings por Environment, los settings son encriptados y expuestos sobre un canal también encriptado. Otra peculiaridad respecto a otros servicios es que estos settings no son para ser utilizados por el sitio estático en sí, sino que son para API's utilizadas como backend dentro del servicio, es decir para las Azure Functions asociadas a este servicio.

Custom Domains

La característica de Custom Domain en un servicio PaaS como la Web App o la API App, es un servicio que requiere un Service Plan mayor al gratuito, en este caso, el servicio "viene de caja" con la funcionalidad de forma gratuita, y para configurarlo basta con crear un registro CNAME que apunte a la url del sitio estático *.azurestaticapps.net.

Custom Domains

Functions

En este apartado localizamos todas las Azure Function que están definidas en el código del repositorio, por defecto la carpeta "api" de la raíz.

Estas Azure Function tienen las siguientes características:

  • Tienen seguridad integrada con acceso directo a los datos de autenticación y autorización basada en roles de usuario.
  • Enrutado sin necesidad de configurar CORS.
  • Son V3, compatibles con Node.js 12.
  • Triggers HTTP y bindings de salida.

Pero también tiene estas limitaciones o restricciones:

  • La ruta de la API debe tener el prefijo "api".
  • Deben estar desarrolladas en JavaScript.
  • Triggers y binding están limitados a HTTP.
  • Los logs sólo están disponibles si añades Application Insights a las Functions.

Environments

Una de las características del servicio, es que crea Environments a partir de Pull Requests, permitiéndote previsualizar en un entorno previo a producción cómo ha quedado la funcionalidad. Esto, que a priori es una técnica que se utiliza en los pipelines de CI / CD para validar, aceptar y desplegar sin realizar cortes en el servicio, lo realiza por defecto este servicio evitando así, tener que crear y definir toda la estrategia al completo.

Cuando es aceptado el PR, automáticamente se produce el despliegue en el slot principal.

Las principales limitaciones en este apartado:

  • La url del sitio generado para el PR es pública a pesar de que el repositorio de GitHub sea privado.
  • Actualmente el número de Environments de pre-producción está limitado a uno. A futuro, cuando el servicio tenga otros SKU de pago, seguramente se ampliará el número de environments.

Role management

En este apartado se puede establecer una gestión de roles con una limitación temporal para poder acceder a los contenidos, para ello, se pulsa en invitar y se crea un link de invitación.

Role Management

Una vez generado el link, el invitado accede a esa url y se autentica con el proveedor que previamente se ha seleccionado en la invitación.

Role Management

Y por último realiza el consentimiento antes de acceder a los recursos.

Role Management

GitHub Actions

GitHub Actions es la solución de GitHub para automatizar, personalizar y ejecutar workflows que permitan desplegar una solución desde un repositorio de GitHub.

Al igual que los ficheros yaml de los pipelines de Azure DevOps, GitHub tiene su alternativa también basada en ficheros yaml. Estas automatizaciones, como las de DevOps, permiten crear artefactos, descargar dependencias, validar la calidad de código, automatizar tests, e infinidad de posibilidades que se pueden combinar para construir un workflow que se ajuste a las necesidades de una solución.

Con estas premisas, al final se puede construir una solución end-to-end desde su creación y desarrollo del código en el repositorio hasta verlo desplegado y publicado en un servicio PaaS.

GitHub Actions y Static Web App

Durante la creacion del sitio hemos establecido la comunicación con un repositorio de GitHub, en el cual se ha creado un workflow que es desencadenado cuando se producen cambios en él.

Este workflow define cómo es desencadenado, y las acciones que realiza.

name: Azure Static Web Apps CI/CD

on:
  push:
    branches:
      - gh-pages
  pull_request:
    types: [opened, synchronize, reopened, closed]
    branches:
      - gh-pages

jobs:
  build_and_deploy_job:
    if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
    runs-on: ubuntu-latest
    name: Build and Deploy Job
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build And Deploy
        id: builddeploy
        uses: Azure/static-web-apps-deploy@v0.0.1-preview
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ZEALOUS_TREE_02DE01503 }}
          repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
          action: "upload"
          ###### Repository/Build Configurations - These values can be configured to match you app requirements. ######
          # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
          app_location: "/" # App source code path
          api_location: "api" # Api source code path - optional
          app_artifact_location: "" # Built app content directory - optional
          ###### End of Repository/Build Configurations ######

  close_pull_request_job:
    if: github.event_name == 'pull_request' && github.event.action == 'closed'
    runs-on: ubuntu-latest
    name: Close Pull Request Job
    steps:
      - name: Close Pull Request
        id: closepullrequest
        uses: Azure/static-web-apps-deploy@v0.0.1-preview
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ZEALOUS_TREE_02DE01503 }}
          action: "close"

En el apartado de los trigger, en este caso:

  • Con un push en la rama gh-pages.
  • Con los Pull Requests abiertos, sincronizados, reabiertos o cerrados

Las acciones o trabajos que lleva a cabo en el caso de los Pull Request cerrados, invoca a una Action con el token de la Static Web App y el parámetro "close".

En el resto de las casuísticas, con la misma Action le envía estos parámetros:

  • Token Azure Static Web App
  • Token del Repositorio de GitHub
  • Action "updated"
  • Path relativo de la App dentro del repositorio
  • Path relativo de la API si la hubiera
  • Path relativo del directorio del artefacto si éste existiera

Por supuesto, todos los tokens como secure string, es decir encriptados de forma automática desde la creación del servicio PaaS en el Portal de Azure.

Conclusiones

Esta solución está aún en preview, y seguramente sufra cambios cuando se consolide y esté más madura. Tiene limitaciones, por ejemplo, que no esté integrada con Azure DevOps, que, aunque todo hace sospechar lo peor para Azure DevOps, es hoy por hoy la plataforma más completa para ALM desde mi humilde opinión.

La idea es muy buena, crear un sitio estático hoy en día es muy habitual, y tener este tipo de soluciones que te permitan desplegar de forma gratuita, con buenas prácticas de DevOps, haciendo CI / CD sin posibilidad de que se pueda desplegar de forma manual, es una buena noticia para el mundo de los desarrolladores.

Ampliar la funcionalidad con Azure Functions también es un punto muy bueno, a pesar de la limitación tecnológica a JavaScript, aunque por otro lado es comprensible, si estamos hablando de un sitio estático.

Estos son los JavaScript Frameworks con los que se puede desarrollar una solución estática compatible con el servicio:

  • Angular CLI
  • Vue CLI
  • React CLI

Generadores de sitios estáticos:

  • Gatsby CLI
  • Hugo
  • Jekyll

Para empezar a crear tu sitio estático, puedes ver este post en el que se construye un sitio estático con GatsbyJS.

Buy Me A Coffee