> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Imponer una lista de verificación de migración en cada pull request (PR)

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Aplicar una lista de verificación de migración en cada PR" description="Crea una skill de repositorio que haga que Devin detecte operaciones destructivas, verifique la seguridad del rollback y valide los cambios de esquema siempre que un PR incluya migraciones de base de datos." prompt="Crea un archivo de skill en .agents/skills/migration-checklist/migration-checklist.md que le enseñe a Devin a revisar cada migración de base de datos en un PR en busca de operaciones destructivas, índices faltantes en claves foráneas, seguridad del rollback y desviaciones de esquema, y bloquee el PR hasta que todas las comprobaciones se superen." category="Core Devin" features="Skills" />

<div className="uc-detail-wrapper">
  <Tip>¿No quieres configurarlo manualmente? Pega un enlace a esta página en una sesión de Devin y pídele que lo configure todo por ti.</Tip>

  <Steps>
    <Step title="Crea la habilidad de lista de comprobación para la migración">
      Una skill de repositorio es un archivo markdown que haces commit en `.agents/skills/<your-skill>/` en cualquiera de tus repositorios. Devin ve todas las skills en todos los repositorios conectados: puedes activarlas manualmente o Devin puede decidir activarlas automáticamente cuando detecta una situación relevante. Esta skill le indica a Devin exactamente cómo revisar las migraciones de base de datos antes de abrir o actualizar una solicitud de extracción de código (pull request, PR), detectando los errores que la revisión de código suele pasar por alto.

      Haz commit de `.agents/skills/migration-checklist/migration-checklist.md` en tu repositorio:

      ```markdown theme={null}
      # Lista de verificación de seguridad para migraciones

      ## Descripción
      Revisa cada migración de base de datos en el PR actual para detectar problemas de seguridad
      antes de abrir o actualizar el pull request.

      ## Cuándo usar
      Invoca esta habilidad siempre que el diff del PR incluya archivos nuevos o modificados
      en `db/migrate/` (Rails), `migrations/` (Django), o
      `prisma/migrations/` (Prisma).

      ## Lista de verificación

      ### 1. Detectar operaciones destructivas
      Analiza cada archivo de migración en busca de:
      - `DROP TABLE` o `drop_table`
      - `DROP COLUMN`, `remove_column`, o eliminación de columna
      - `TRUNCATE`
      - Cambios de tipo de dato que pierden precisión (p. ej. `text` → `varchar(50)`)

      Si se encuentra alguno, agrega un comentario al PR señalando la operación y
      confirmando si existe un paso de respaldo de datos en la migración.

      ### 2. Verificar índices de claves foráneas
      Para cada `add_reference`, `add_foreign_key`, o nueva columna que termine
      en `_id`, confirma que existe un índice correspondiente. Si no existe, agrégalo a la
      migración antes de hacer el commit.

      ### 3. Verificar seguridad del rollback
      - Ejecuta `bin/rails db:migrate:rollback STEP=<n>` (donde n = número de
        nuevas migraciones) contra la base de datos de prueba.
      - Si el rollback falla, agrega un método `down` o un bloque reversible y
        vuelve a intentarlo.
      - Reporta cualquier migración irreversible en la descripción del PR.

      ### 4. Validar que el archivo de esquema esté actualizado
      Después de ejecutar las migraciones, compara `db/schema.rb` (o `structure.sql`)
      con la versión en el PR. Si difieren, regenera el archivo de esquema
      e inclúyelo en el commit.

      ### 5. Ejecutar pruebas de modelos
      Ejecuta `bin/rails test test/models/` para detectar validaciones o
      asociaciones rotas por cambios en el esquema. Todas las pruebas deben pasar antes
      de abrir el PR.
      ```

      Una vez que se haya confirmado este archivo, Devin lo considera una habilidad disponible. Cada vez que una sesión interactúe con archivos de migración en este repositorio, Devin puede activar la lista de verificación automáticamente, o puedes invocarla manualmente en cualquier momento.
    </Step>

    <Step title="Vea el disparador de la habilidad en una migración real">
      Cuando Devin trabaja en una tarea que agrega o modifica un archivo de migración, lee el diff, detecta la habilidad de lista de verificación de migraciones y sigue la lista antes de abrir la PR. Así es como se ve en la práctica:

      1. **Escanea el diff** — Devin ve un archivo nuevo en `db/migrate/` y activa la habilidad de lista de verificación de migraciones
      2. **Marca una operación destructiva** — La migración elimina una columna `legacy_email`. Devin agrega un comentario en la PR:
         > `remove_column :users, :legacy_email` es una operación destructiva.
         > Verificado: la migración incluye un paso de copia de seguridad de datos que copia los valores a
         > `user_archives` antes de la eliminación.
      3. **Agrega un índice faltante** — La migración agrega `account_id` a la tabla `invoices` pero no tiene índice. Devin agrega `add_index :invoices, :account_id` al archivo de migración
      4. **Ejecuta el rollback** — Devin ejecuta `bin/rails db:migrate:rollback STEP=1` contra la base de datos de pruebas. Se ejecuta correctamente
      5. **Regenera el esquema** — Devin ejecuta `bin/rails db:schema:dump`, detecta un diff en `db/schema.rb` e incluye el archivo actualizado en el commit
      6. **Ejecuta las pruebas de modelos** — Todas las pruebas de modelos pasan. Devin abre la PR con un resumen de cada verificación

      La descripción de la PR incluye una lista de verificación que muestra qué se aprobó y qué corrigió Devin, de modo que los revisores puedan centrarse en la lógica de negocio en lugar de en la mecánica de la migración.
    </Step>

    <Step title="Adapta la skill a tu ORM y a tu stack">
      La lista de verificación anterior está orientada a Rails, pero la misma estructura funciona para cualquier ORM. Pídele a Devin que reescriba la skill para tu stack:

      <PromptBlock>
        ```txt Adaptar para Django theme={null}
        Reescribe la skill de lista de verificación de migraciones para nuestro proyecto de Django:
        - Analiza los archivos en `apps/*/migrations/` en busca de operaciones destructivas,
          como RemoveField, DeleteModel y AlterField con pérdida de datos
        - Después de ejecutar `python manage.py migrate`, verifica que
          `python manage.py showmigrations` no muestre migraciones sin aplicar
        - Ejecuta `python manage.py test --tag=models` para validar los cambios de esquema
        - Comprueba que las migraciones tengan un `reverse_code` o un `RunSQL` inverso
          para garantizar la seguridad del rollback
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Adaptar para Prisma theme={null}
        Reescribe la skill de lista de verificación de migraciones para nuestro proyecto de Prisma:
        - Analiza los archivos en `prisma/migrations/` en busca de DROP TABLE, DROP COLUMN
          y ALTER COLUMN que reduzcan la longitud de los campos
        - Ejecuta `npx prisma migrate deploy` sobre la base de datos de pruebas y
          confirma que se ejecute correctamente
        - Ejecuta `npx prisma migrate diff` para verificar que schema.prisma coincida
          con el estado de las migraciones aplicadas
        - Ejecuta `npm test -- --grep "model"` para detectar relaciones rotas
        ```
      </PromptBlock>
    </Step>

    <Step title="Ve ampliando la lista de comprobación con el tiempo">
      Cada incidente de migración revela una brecha que la checklist no cubrió. Después de cada uno, agrega una regla: es un commit de una sola línea en el archivo de skill.

      Estas son incorporaciones habituales que los equipos hacen después de incidentes reales:

      ```markdown theme={null}
      ### 6. Enforce migration naming conventions
      Reject migrations that don't follow the pattern
      `YYYYMMDDHHMMSS_verb_noun.rb` (e.g. `add_index_to_invoices`).
      Rename the file if needed.

      ### 7. Check for long-running locks
      Flag any `add_column` on tables with >1M rows that doesn't use
      `disable_ddl_transaction!` (Postgres) or `ALGORITHM=INPLACE`
      (MySQL). Large tables need non-blocking migrations.

      ### 8. Require a migration test
      Ensure a corresponding test file exists at
      `test/migrations/YYYYMMDDHHMMSS_migration_name_test.rb`.
      If missing, generate a skeleton test that runs the migration
      up and down.
      ```

      Como el archivo de skill está en tu repositorio, estas reglas pasan por revisión de código: todo tu equipo está de acuerdo sobre qué se comprueba y siempre están sincronizadas con tus herramientas de migración.
    </Step>
  </Steps>
</div>
