Saltearse al contenido

Tutorial: Primeros pasos con Astro — 10. Despliegue automático con Astro y Content Island usando GitHub Actions

00:00 / 00:00

10. Despliegue automático con Astro y Content Island usando GitHub Actions

GitHub Pages es un servicio de alojamiento web que GitHub ofrece a los usuarios de sus repositorios. Además, este servicio es gratuito para repositorios públicos, lo que hace que sea una excelente opción para alojar proyectos.

En este ejemplo, vamos a ver cómo desplegar el proyecto "Get Started Astro" de Content Island en GitHub Pages.

Paso 1: Crear un repositorio

Lo primero que necesitamos para desplegar este proyecto es un repositorio de GitHub:

  • Abrimos nuestra cuenta en Github y le damos a crear uno nuevo.
  • Le damos un nombre.
  • Vamos a crearlo público, para utilizarlo de forma gratuita.
  • Y le damos directamente al botón de crear sin añadir ningún fichero.

Copiamos la URL del repositorio que acabamos de crear y lo clonamos en nuestro ordenador, en una carpeta vacía utilizando el siguiente comando:

git clone <URL del repositorio> .

Ponemos un punto al final para que git no añada una carpeta extra con el nombre del repositorio.

Ahora, teniendo clonado el repositorio con el proyecto de Astro, simplemente copiamos el contenido de la carpeta blog-site a la que acabamos de crear y lo subimos al repositorio con los siguientes comandos:

git add .
git commit -m "Initial commit"
git push

Vemos que ahora ya esta subido el proyecto a nuestro repositorio de GitHub.

Paso 2: Configurar despliegue

Para configurar el despliegue en GitHub Pages, necesitamos crear un workflow en GitHub Actions. Para ello, creamos una carpeta .github/workflows en la raíz del proyecto y añadimos un fichero, con el nombre que queramos, yo le voy a poner deploy.yml con el siguiente contenido:

  • Le damos un nombre al workflow, que más adelante nos ayudará a identificarlo en GitHub.
  • Indicamos el momento en el que se ejecutará, en este caso, cada vez que hagamos un push a la rama main.
  • Y ahora definimos un job que vamos a llamar deploy y se ejecutará en una máquina virtual de Ubuntu.
  • Como esta máquina virtual no tiene el código fuente de nuestro proyecto, el primer paso es clonar el repositorio, al igual que hicimos nosotros en nuestra máquina local. Para ello, utilizamos una acción ya predefinida de Github Actions llamada actions/checkout y usamos la version 4.
  • Instalamos las dependencias necesarias con el comando npm ci que utiliza el fichero package-lock.json.
  • Ejecutamos la build.
  • Subimos el resultado de la build a un artefacto, con una acción de GitHub Actions que se llama upload-pages-artifact y le indicamos la carpeta que queremos subir.
  • Y por último, utilizamos la acción deploy-pages para desplegar el artefacto en GitHub Pages. Como indica la documentación oficial de la acción `deploy-pages`, es importante añadir los permisos de escritura para id-token y pages.

./.github/workflows/deploy.yml

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - main

permissions:
  pages: write
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Clone repository
        uses: actions/checkout@v4

      - name: Install
        run: npm ci

      - name: Build
        run: npm run build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

      - name: Deploy
        uses: actions/deploy-pages@v4

Antes de hacer el push, es importante que configuremos un par de cosas en el proyecto.

Por un lado, si vamos al apartado de Settings del repositorio, en la sección de Pages, podemos ver que por defecto está configurado para que el despliegue se haga desde una branch. tenemos que cambiarlo para habilitar el despliegue desde GitHub Actions.

Habilitar despliegue desde Github Actions

Por otro, recordemos que cuando se ejecuta la build del proyecto, se conecta con nuestro proyecto de Content Island para recuperar los datos de cada Post, por lo que necesitamos configurar la variable de entorno CONTENT_ISLAND_SECRET_TOKEN en el repositorio de GitHub. Para ello, vamos a Settings > Secrets > Actions > New repository secret y añadimos la variable, y obtenemos el valor que nos proporciona Content Island en la pestaña General.

Ahora que tenemos este secreto, lo utilizamos como variable de entorno en el fichero deploy.yml:

./.github/workflows/deploy.yml

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - main

permissions:
  pages: write
  id-token: write

+ env:
+   CONTENT_ISLAND_SECRET_TOKEN: ${{secrets.CONTENT_ISLAND_SECRET_TOKEN}}

jobs:
  deploy:
    runs-on: ubuntu-latest
...

Ahora si, hacemos commit y push al repositorio y esperamos a que se ejecute el workflow.

git add .
git commit -m "add workflow"
git push

Paso 3: Mostrar URL desplegada

Como vemos el proceso ha terminado correctamente, pero no sabemos en que URL se ha desplegado. Esta URL la podemos ver en el apartado de Settings > Pages del repositorio.

Si queremos que aparezca en el propio workflow cuando termine, podemos actualizar el fichero deploy.yml:

  • Indentificamos el step deploy con un id.
  • Y añadimos un environment con el nombre que queramos y la URL que nos proporciona dicho step.

./.github/workflows/deploy.yml

...

jobs:
  deploy:
    runs-on: ubuntu-latest
+   environment:
+     name: github-pages
+     url: ${{ steps.deploy.outputs.page_url }}
    steps:
      - name: Clone repository
        uses: actions/checkout@v4

      - name: Install
        run: npm ci

      - name: Build
        run: npm run build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

      - name: Deploy
+       id: deploy
        uses: actions/deploy-pages@v4

Ahora, si volvemos a hacer un push al repositorio, veremos que al finalizar el workflow nos aparece la URL en la que se ha desplegado.

git add .
git commit -m "add environment"
git push

Paso 4: Problema con la URL base

Aunque parece que ya tenemos todo listo, si navegamos a cualquier post, veremos que no se muestra correctamente. Esto es debido a que por defecto, Github Pages utiliza el nombre del repositorio como URL base donde despliega la aplicación. Es decir, si despliegas varias aplicaciones con esa misma cuenta de Github, cada una de ellas se desplegará en una ruta diferente (cada una con su nombre de repositorio), pero todas ellas compartirán el mismo dominio (<nombre de usuario>.github.io).

Para solucionar este problema, Astro nos permite configurar la propiedad `base` tanto en el fichero astro.config.mjs como desde la línea de comandos y si tocamos esta propiedad, es necesario utilizar la variable de entorno import.meta.env.BASE_URL cuando navegamos a una ruta en cualquier href.

Por lo tanto, vamos a actualizar la build del workflow:

  • Ahora, necesitamos pasarle una opción extra a este comando, asi que utilizamos el doble guión -- para así poder pasarle todos los argumentos que queramos. En este caso, el argumento --base y como valor, necesitamos el nombre del repositorio.
  • Si queremos que este workflow quede lo más genérico posible para que nos sirva para cualquier proyecto, podemos utilizar la acción configure-pages de Github, que como salida, nos proporciona la URL base del proyecto.

./.github/workflows/deploy.yml

...

      - name: Install
        run: npm ci

+     - name: Setup Pages
+       id: pages
+       uses: actions/configure-pages@v5

      - name: Build
-       run: npm run build
+       run: npm run build -- --base "${{ steps.pages.outputs.base_path }}"
...

A continuación, actualizamos todos los href del proyecto para que utilicen la variable de entorno import.meta.env.BASE_URL como URL base:

Es decir, actualizamos el fichero index.astro:

./src/pages/index.astro

...
    <ul class="posts__list">
      {
        posts.map(post => (
          <li>
            <article class="post">
              <a
-               href={`/posts/${post.title
+               href={`${import.meta.env.BASE_URL}/posts/${post.title
                  .toLowerCase()
                  .trim()
                  .replace(/[^a-z0-9\s-]/g, '')
                  .replace(/\s+/g, '-')}`}
              >
                <Image
                  src={post.image.link}
                  alt={post.image.name}
                  width={250}
                  height={100}
                  class:list={'post__image'}
                  loading="eager"
                />
              </a>
              <div class="post__text">
                <div class="post__header">
                  <p class="post__date">
                    <time datetime="2025-03-05">{date(post.date)}</time>
                  </p>
                  <a
-                   href={`/posts/${post.title
+                   href={`${import.meta.env.BASE_URL}/posts/${post.title
                      .toLowerCase()
                      .trim()
                      .replace(/[^a-z0-9\s-]/g, '')
                      .replace(/\s+/g, '-')}`}
                    class="post__title"
                  >
                    <h2>{post.title}</h2>
                  </a>
                </div>
                <div>
                  <p class="post__description">{post.summary}</p>
                </div>
              </div>
            </article>
          </li>
        ))
      }
    </ul>
...

Y el fichero Header.astro:

./src/components/Header.astro

<header class="header">
  <nav class="menu">
    <ul>
      <li>
-       <a href="/" class="menu__item"> CurioVerso</a>
+       <a href={import.meta.env.BASE_URL} class="menu__item"> CurioVerso</a>
      </li>
      <div class="menu__right">
-       <li><a href="/" class="menu__item">All Post</a></li>
+       <li><a href={import.meta.env.BASE_URL} class="menu__item">All Post</a></li>
-       <li><a href="/about/" class="menu__item">About</a></li>
+       <li><a href={`${import.meta.env.BASE_URL}/about/`} class="menu__item">About</a></li>
      </div>
    </ul>
  </nav>
</header>
...

Ya podemos hacer un nuevo push al repositorio y comprobar si funciona correctamente.

git add .
git commit -m "fix base url"
git push

¡Y listo! Ya tenemos nuestro proyecto con Content Island y Astro desplegado en GitHub Pages.