> ## 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.

# Imporre una checklist di migrazione per ogni 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="Applicare una checklist di migrazione a ogni PR" description="Crea una skill del repository che permetta a Devin di individuare operazioni distruttive, verificare la sicurezza del rollback e convalidare le modifiche allo schema ogni volta che una PR tocca le migrazioni del database." prompt="Crea un file di skill in .agents/skills/migration-checklist/migration-checklist.md che insegni a Devin a esaminare ogni migrazione del database in una PR per individuare operazioni distruttive, indici mancanti sulle chiavi esterne, sicurezza del rollback e schema drift — quindi bloccare la PR finché tutti i controlli non vengono superati." category="Core Devin" features="Skills" />

<div className="uc-detail-wrapper">
  <Tip>Non vuoi configurare tutto manualmente? Incolla un collegamento a questa pagina in una sessione di Devin e chiedigli di impostare tutto per te.</Tip>

  <Steps>
    <Step title="Crea la skill per la checklist di migrazione">
      Una repository skill è un file markdown che esegui il commit in `.agents/skills/<your-skill>/` in uno qualsiasi dei tuoi repository. Devin vede tutte le skill presenti in tutti i repository collegati: puoi attivarle manualmente oppure Devin può decidere di attivarle automaticamente quando rileva una situazione rilevante. Questa skill indica a Devin esattamente come revisionare le migrazioni del database prima di aprire o aggiornare una pull request (PR), intercettando gli errori che di solito sfuggono alla code review.

      Esegui il commit di `.agents/skills/migration-checklist/migration-checklist.md` nel tuo repository:

      ```markdown theme={null}
      # Migration Safety Checklist

      ## Description
      Review every database migration in the current PR for safety issues
      before opening or updating the pull request.

      ## When to use
      Invoke this skill whenever the PR diff includes new or modified files
      in `db/migrate/` (Rails), `migrations/` (Django), or
      `prisma/migrations/` (Prisma).

      ## Checklist

      ### 1. Detect destructive operations
      Scan each migration file for:
      - `DROP TABLE` or `drop_table`
      - `DROP COLUMN`, `remove_column`, or column removal
      - `TRUNCATE`
      - Data-type changes that lose precision (e.g. `text` → `varchar(50)`)

      If any are found, add a PR comment flagging the operation and
      confirming whether a data backup step exists in the migration.

      ### 2. Verify foreign-key indexes
      For every `add_reference`, `add_foreign_key`, or new column ending
      in `_id`, confirm a matching index exists. If not, add one to the
      migration before committing.

      ### 3. Check rollback safety
      - Run `bin/rails db:migrate:rollback STEP=<n>` (where n = number of
        new migrations) against the test database.
      - If rollback fails, add a `down` method or reversible block and
        retry.
      - Report any irreversible migrations in the PR description.

      ### 4. Validate schema file is up-to-date
      After running migrations, diff `db/schema.rb` (or `structure.sql`)
      against the version in the PR. If they differ, regenerate the schema
      file and include it in the commit.

      ### 5. Run model tests
      Execute `bin/rails test test/models/` to catch validations or
      associations broken by schema changes. All tests must pass before
      the PR is opened.
      ```

      Una volta eseguito il commit di questo file, Devin lo considera una skill disponibile. Ogni volta che una sessione coinvolge file di migrazione in questa repository, Devin può attivare automaticamente la checklist — oppure puoi richiamarla manualmente in qualsiasi momento.
    </Step>

    <Step title="Vedi come si attiva la skill in una migrazione reale">
      Quando Devin lavora a un task che aggiunge o modifica un file di migration, legge il diff, associa la skill *migration checklist* e segue la checklist prima di aprire la PR. Ecco come avviene in pratica:

      1. **Analizza il diff** — Devin vede un nuovo file in `db/migrate/` e attiva la skill *migration checklist*
      2. **Contrassegna un'operazione distruttiva** — La migration rimuove la colonna `legacy_email`. Devin aggiunge un commento alla PR:
         > `remove_column :users, :legacy_email` è un'operazione distruttiva.
         > Verificato: la migration include uno step di backup dei dati che copia i valori in
         > `user_archives` prima della rimozione.
      3. **Aggiunge un indice mancante** — La migration aggiunge `account_id` alla tabella `invoices` ma non prevede alcun indice. Devin aggiunge `add_index :invoices, :account_id` al file di migration
      4. **Esegue il rollback** — Devin esegue `bin/rails db:migrate:rollback STEP=1` sul database di test, che va a buon fine
      5. **Rigenera lo schema** — Devin esegue `bin/rails db:schema:dump`, rileva un diff in `db/schema.rb` e include il file aggiornato nel commit
      6. **Esegue i test dei modelli** — Tutti i test dei modelli passano. Devin apre la PR con un riepilogo di ogni controllo

      La descrizione della PR include una checklist che mostra quali controlli sono passati e cosa Devin ha corretto, così i revisori possono concentrarsi sulla business logic invece che sulla meccanica della migration.
    </Step>

    <Step title="Adatta la skill al tuo ORM e stack tecnologico">
      La checklist sopra è pensata per Rails, ma la stessa struttura funziona con qualsiasi ORM. Chiedi a Devin di riscrivere la skill per il tuo stack:

      <PromptBlock>
        ```txt Adatta per Django theme={null}
        Riscrivi la skill della checklist di migrazione per il nostro progetto Django:
        - Analizza i file in `apps/*/migrations/` alla ricerca di operazioni distruttive
          come RemoveField, DeleteModel e AlterField con perdita di dati
        - Dopo aver eseguito `python manage.py migrate`, verifica che
          `python manage.py showmigrations` non mostri migrazioni non applicate
        - Esegui `python manage.py test --tag=models` per convalidare le modifiche allo schema
        - Controlla che le migrazioni abbiano un `reverse_code` o un reverse `RunSQL`
          per garantire la sicurezza del rollback
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Adatta per Prisma theme={null}
        Riscrivi la skill della checklist di migrazione per il nostro progetto Prisma:
        - Analizza i file in `prisma/migrations/` alla ricerca di DROP TABLE, DROP COLUMN
          e ALTER COLUMN che riducono l’ampiezza del campo
        - Esegui `npx prisma migrate deploy` contro il database di test e
          verifica che vada a buon fine
        - Esegui `npx prisma migrate diff` per verificare che schema.prisma corrisponda
          allo stato delle migrazioni applicate
        - Esegui `npm test -- --grep "model"` per intercettare relazioni interrotte
        ```
      </PromptBlock>
    </Step>

    <Step title="Amplia la checklist nel tempo">
      Ogni incidente di migrazione rivela una lacuna che la checklist non copre. Dopo ognuno, aggiungi una regola: basta un commit di una riga al file delle skill.

      Ecco le aggiunte più comuni che i team fanno dopo incidenti reali:

      ```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.
      ```

      Poiché il file delle skill si trova nel tuo repository, queste regole passano attraverso la code review — tutto il team è allineato su ciò che viene verificato e rimane sempre in sincronia con i tuoi strumenti di migrazione.
    </Step>
  </Steps>
</div>
