| name | drupaltools-migration-plan |
| description | Generate comprehensive Drupal migration plans with entity mapping, ETL strategies, rollback procedures, and source analysis based on best practices from the Drupal migration guide. |
Drupal Migration Plan Generator
A comprehensive skill for planning Drupal migrations from older versions (7.x, 6.x) to modern Drupal (9+, 10+). This skill provides structured guidance for source analysis, entity mapping, migration architecture, testing strategies, and rollback procedures.
Overview
When assisting with Drupal migrations, this skill provides:
- Source Site Analysis: Identify entities, fields, and configurations to migrate
- Entity Mapping: Document mappings between source and target structures
- ETL Strategy: Define extract, transform, and load procedures
- Testing Plans: Comprehensive checklists for validation
- Rollback Procedures: Backup and recovery strategies
When to Use
Activate this skill when the user asks about:
- Planning a migration from Drupal 7.x/6.x to Drupal 9+/10+
- Creating migration documentation for stakeholders
- Designing ETL strategies for content migration
- Preparing testing procedures for migrated content
- Planning rollback strategies and disaster recovery
- Documenting entity mappings between source and target sites
- Migration module recommendations
Trigger phrases:
- "How do I plan a Drupal 7 to 10 migration?"
- "What entities do I need to migrate?"
- "How do I test my migration?"
- "What's the rollback procedure?"
- "Which migration modules should I use?"
- "How do I map old fields to new ones?"
- "migration plan for drupal"
- "drupal upgrade strategy"
Migration Planning Process
Step 1: Source Site Analysis
Document all entities on the source site:
Entities to inventory:
| Entity Type | Check For | Notes |
|---|
| Nodes | Content types, fields, revisions | Count per type |
| Users | Roles, profile fields | Include blocked users? |
| Taxonomy | Vocabularies, term hierarchy | Deep nesting? |
| Files | Public, private, attached to fields | Size and count |
| Paragraphs | Paragraph types, parent references | Revisions? |
| Blocks | Custom blocks, placements | Block types |
| Menus | Menu links, hierarchy depth | Custom menus |
| Views | Displays, exposed filters | Complex views? |
| Forms | Webforms, contact forms | Submissions? |
| URL Aliases | Patterns, redirects | Custom aliases |
Tools for analysis:
- For Drupal 7.x/6.x: Use drupal-report
- Create Views on source site to get entity overviews
- Document database credentials
Step 2: Migration Architecture
Required modules:
| Module | Type | Purpose |
|---|
| migrate | Core | Migration framework |
| migrate_drupal | Core | Drupal-to-Drupal migrations |
| migrate_plus | Contrib | Enhanced migration tools |
| migrate_tools | Contrib | Drush commands |
| migrate_devel | Contrib (optional) | Debugging |
| config_devel | Contrib (optional) | YAML management |
Custom module structure:
modules/custom/migrate_[source]_[target]/
โโโ migrate_[source]_[target].info.yml
โโโ migrations/
โ โโโ migrate_plus.migration_group.[group].yml
โ โโโ migrate_plus.migration.[entity].yml
โโโ src/
โ โโโ Plugin/migrate/source/
โ โโโ Plugin/migrate/process/
โ โโโ Plugin/migrate/destination/
โโโ README.md
Step 3: Entity Mapping
Create mapping documentation:
| Source | Source Fields | Target | Target Fields | Process | Notes |
|---|
| node:article | title, body, field_tags | node:blog | title, body, field_categories | default | Tags โ Categories |
| user | name, mail, field_bio | user | name, mail, field_profile | default | Bio โ Profile |
Field migration considerations:
vid (revision ID): Let Drupal generate new ones
uuid: Let Drupal generate to avoid conflicts
nid: Store old nid in custom field for reference
- Text with embedded files: Use DOMDocument for parsing
- Multilingual: Track translation sources carefully
- Paragraphs: Watch for asymmetric translations
Step 4: Migration Groups
Organize migrations by dependency:
- users
- taxonomy_terms
- files
- nodes_basic
- nodes_with_media
- nodes_with_paragraphs
- menu_links
- url_aliases
Step 5: ETL Strategy
Extract:
- Use custom source plugins for complex SQL
- Use
prepareRow() for row-level filtering (not query() for distinct)
- Skip rows:
return FALSE in prepareRow()
Transform:
- Process plugins for field transformations
- DOMDocument for HTML parsing
- Migrate files before content that references them
Load:
- Migrate data only, not settings
- Use Drush commands, not UI
- Continuous config import/export during development
Step 6: Testing Checklist
Pre-migration:
Post-migration content:
Post-migration multilingual:
Post-migration navigation:
Post-migration workflows:
Step 7: Rollback Strategy
Pre-production backups:
drush sql:dump --result-file=/backup/pre-migration.sql
drush config:export --destination=/backup/config-pre-migration
Rollback commands:
drush migrate:stop [migration_id]
drush migrate:reset-status [migration_id]
drush migrate:rollback [migration_id]
drush sql:cli < /backup/pre-migration.sql
Post-migration cleanup:
- Uninstall migration modules
- Remove migration DB credentials from settings.php
- Archive migration YAML files
Database Configuration
Add to sites/default/settings.php:
$databases['migrate']['default'] = [
'database' => 'drupal7',
'username' => 'drupal7',
'password' => 'drupal7',
'prefix' => '',
'host' => 'database.7x-website.host',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
];
Essential Drush Commands
drush migrate:status
drush migrate:import [migration_id]
drush migrate:import [migration_id] --update
drush migrate:rollback [migration_id]
drush migrate:import --group=[group_id]
Best Practices
- Get an overview of source site before planning (follow Main menu as anonymous user)
- Always use migrate_plus for enhanced migration capabilities
- Create a custom module to hold migration plugins and YAML files
- Migrate only data, never settings or permissions
- Clone core YAML files to your module, don't reference directly
- Keep migrations simple - prefer custom plugins over complex dependencies
- Use generic module names for easy reuse in future projects
- Group related migrations that run together
- Always use Drush, never the UI for running migrations
- Document everything in README with mappings and commands
- Use config_devel for easier YAML management during development
- Copy private files with rsync before content migration
- Store old nid in custom field for testing reference
- Avoid vid/uuid conflicts - let Drupal generate new values
- Filter rows by returning
FALSE in prepareRow()
- Parse HTML with PHP DOMDocument for embedded content
- Clean up - uninstall migration modules after production
Common Issues and Solutions
| Issue | Solution |
|---|
| vid/uuid errors | Don't migrate these, let Drupal generate new |
| Multilingual revision conflicts | Track translation sources separately |
| HTML embedded images | Use DOMDocument to extract and migrate |
| Distinct rows in query | Use prepareRow() filtering, not SQL DISTINCT |
| Demo content ID conflicts | Clear demo content before production migration |
| Asymmetric paragraph translations | Handle each language variant separately |
References
Keywords
drupal migration, migrate api, migrate_plus, drupal 7 to 10, drupal 6 to 9, upgrade drupal, migration plan, entity mapping, content migration, etl, rollback migration, migration testing, migration drush, migrate_tools, migration architecture, migrate_devel