Saltar al contenido principal

Verificación de seguridad en migraciones

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

[Repositorio de soporte]

Los cambios descritos en esta sección pueden consultarse en PR #8 del repositorio de soporte.

Verificación de seguridad en migraciones

Dado que la base de datos es un componente crítico de nuestra aplicación, debemos asegurarnos de que los cambios que realicemos no causen problemas. Las migraciones mal planificadas pueden provocar pérdida de datos, tiempo de inactividad de la aplicación y otros inconvenientes. Atlas proporciona un mecanismo para verificar que una migración es segura de ejecutar. Este mecanismo se denomina linting de migraciones y en esta sección mostraremos cómo usarlo para verificar que nuestras migraciones sean seguras.

Linting del directorio de migraciones

Para analizar nuestro directorio de migraciones podemos usar el comando atlas migrate lint. Para demostrarlo, veamos qué ocurre si cambiamos el campo Title del modelo User de opcional a obligatorio:

// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
field.String("email").
Unique(),
-- field.String("title").
-- Optional(),
++ field.String("title"),
}
}

Reejecutemos la generación de código:

go generate ./...

A continuación, generemos automáticamente una nueva migración:

atlas migrate diff user_title_required \
--dir "file://ent/migrate/migrations" \
--to "ent://ent/schema" \
--dev-url "docker://mysql/8/ent"

Se creó un nuevo archivo de migración en el directorio ent/migrate/migrations:

ent/migrate/migrations/20221116051710_user_title_required.sql
-- modify "users" table
ALTER TABLE `users` MODIFY COLUMN `title` varchar(255) NOT NULL;

Ahora, analicemos el directorio de migraciones:

atlas migrate lint --dev-url mysql://root:pass@localhost:3306/dev --dir file://ent/migrate/migrations --latest 1

Atlas indica que la migración podría no ser segura:

20221116051710_user_title_required.sql: data dependent changes detected:

L2: Modifying nullable column "title" to non-nullable might fail in case it contains NULL values

Atlas detectó que la migración no es segura y evitó su ejecución. En este caso, clasificó el cambio como dependiente de datos. Esto significa que el cambio podría fallar dependiendo de los datos concretos en la base de datos.

Atlas puede detectar muchos más tipos de problemas. Para ver la lista completa, consulta la documentación de Atlas.

Linting del directorio en CI

En la sección anterior vimos cómo analizar localmente el directorio de migraciones. Ahora veremos cómo hacerlo en CI (Integración Continua), asegurando así que el historial de migraciones sea seguro antes de fusionarlo con la rama principal.

GitHub Actions es una solución popular de CI/CD de GitHub. Permite definir flujos de trabajo que se activan en eventos del ciclo de vida de un repositorio Git. Por ejemplo, muchos equipos configuran GitHub Actions para ejecutar pruebas unitarias tras cada cambio en el repositorio.

Una característica poderosa de GitHub Actions es su extensibilidad: es muy fácil empaquetar funcionalidades como módulos reutilizables (llamados "actions").

Los equipos que usan GitHub y desean asegurar los cambios en sus esquemas de base de datos pueden usar la acción atlas-action.

Esta acción se utiliza para analizar directorios de migraciones mediante el comando atlas migrate lint. Este comando valida y analiza el contenido de los directorios, generando diagnósticos sobre los cambios:

  • Garantiza que el historial de migraciones pueda reproducirse desde cualquier punto temporal.

  • Protege contra cambios inesperados cuando varios miembros del equipo escriben migraciones concurrentes en el directorio.

  • Detecta cambios destructivos, irreversibles o dependientes de datos que podrían causar fallos.

Uso

Añade un archivo .github/workflows/atlas-ci.yaml a tu repositorio con este contenido:

name: Atlas CI
on:
# Run whenever code is changed in the master branch,
# change this to your root branch.
push:
branches:
- master
pull_request:
paths:
- 'ent/migrate/migrations/*'
jobs:
lint:
services:
# Spin up a mysql:8.0.29 container to be used as the dev-database for analysis.
mysql:
image: mysql:8.0.29
env:
MYSQL_ROOT_PASSWORD: pass
MYSQL_DATABASE: dev
ports:
- "3306:3306"
options: >-
--health-cmd "mysqladmin ping -ppass"
--health-interval 10s
--health-start-period 10s
--health-timeout 5s
--health-retries 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.0.1
with:
fetch-depth: 0 # Mandatory unless "latest" is set below.
- uses: ariga/atlas-action@v0
with:
dir: ent/migrate/migrations
dev-url: mysql://root:pass@localhost:3306/dev

Ahora, cada vez que se realice un pull request con una migración potencialmente insegura, la acción de Atlas se ejecutará y reportará los resultados. Por ejemplo, para nuestro cambio dependiente de datos:

Para una documentación más detallada, consulta la documentación de atlas-action en el sitio web de Atlas.

Solucionemos el problema rellenando la columna title. Añade la siguiente sentencia al archivo de migración:

ent/migrate/migrations/20221116051710_user_title_required.sql
-- modify "users" table
UPDATE `users` SET `title` = "" WHERE `title` IS NULL;

ALTER TABLE `users` MODIFY COLUMN `title` varchar(255) NOT NULL;

Vuelve a calcular el hash del directorio de migraciones:

atlas migrate hash --dir file://ent/migrate/migrations

Al volver a ejecutar atlas migrate lint, podemos ver que el directorio de migraciones ya no contiene cambios inseguros:

atlas migrate lint --dev-url mysql://root:pass@localhost:3306/dev --dir file://ent/migrate/migrations --latest 1

Como no se encuentran problemas, el comando finalizará con un código de salida cero y sin salida.

Cuando confirmemos este cambio en GitHub, la acción de Atlas en GitHub se ejecutará e informará de que el problema está resuelto:

Conclusión

En esta sección, hemos visto cómo usar Atlas para verificar que nuestra migración es segura de ejecutar tanto localmente como en CI.

Con esto concluimos nuestro tutorial sobre cómo actualizar tu proyecto de Ent de migraciones automáticas a migraciones versionadas. Para recapitular, hemos aprendido a:

  • Habilitar el feature flag de migraciones versionadas

  • Crear un script para planificar migraciones automáticamente basándonos en nuestro esquema Ent deseado

  • Actualizar nuestra base de datos de producción para usar migraciones versionadas con Atlas

  • Planificar migraciones personalizadas para nuestro proyecto

  • Verificar migraciones de forma segura usando atlas migrate lint

Próximos pasos

[Para más noticias y actualizaciones de Ent:]