GovHUB Story Migration: A Georgia Custom Drupal Data A P R I L - - PDF document

▶
govhub story migration a georgia custom drupal data
SMART_READER_LITE
LIVE PREVIEW

GovHUB Story Migration: A Georgia Custom Drupal Data A P R I L - - PDF document

GovHUB Story Migration: A Georgia Custom Drupal Data A P R I L S I D E S + L U L L A B O T G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0 G E O R G I A G O V H U B M I G R A T I O N + F


slide-1
SLIDE 1

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0 G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

1

Custom Drupal Data Migration: A Georgia GovHUB Story

A P R I L S I D E S + L U L L A B O T

slide-2
SLIDE 2

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

2

April Sides

S R. D E V E L O P E R + L U L L A B O T

weekbeforenext weekbeforenext aprilsides

slide-3
SLIDE 3

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

3
slide-4
SLIDE 4

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

4
slide-5
SLIDE 5

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

5

Lullabot Migration Team

slide-6
SLIDE 6

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

6

Digital Services Georgia

slide-7
SLIDE 7

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

What we will cover

⭑

Discovery and Planning

⭑

Strategies and Workflow

⭑

Magical Nerdery

7
slide-8
SLIDE 8

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Discovery and Planning

8

Photo by Elodie Oudot on Unsplash

slide-9
SLIDE 9

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Source

⭑

Drupal 7 Multisite (85+ sites)

⭑

Hosted on Acquia

⭑

27 Content Types (15 migrated)

⭑

14 Taxonomy Vocabularies (9 migrated)

⭑

Paragraphs, Field Collections and Entity Embeds

9

Destination

⭑

Drupal 8 Multisite (~6 at a time)

⭑

Hosted on Acquia

⭑

20 Content Types (14 populated)

⭑

17 Taxonomy Vocabularies (10 populated)

⭑

"Micro-content" Types and Entity Embeds

slide-10
SLIDE 10

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

10
slide-11
SLIDE 11

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

11
slide-12
SLIDE 12

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

12
slide-13
SLIDE 13

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

13
slide-14
SLIDE 14

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

14
slide-15
SLIDE 15

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

https://www.drupal.org/project/migration_planner

15
slide-16
SLIDE 16

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

16

Photo by mali maeder from Pexels

SQueaLer

slide-17
SLIDE 17

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

SQueaLer scans

⭑

WYSIWYG string queries:

✩

Object tags

✩

Image tags

✩

Embedded entities

✩

Absolute links

✩

Span tags

✩

iFrames

✩

Script tags

✩

Tables

17

✩

Custom classes

✩

Custom forms

✩

Email links

✩

Style tags and attributes

✩

Social network links

✩

Video iFrames

✩

Links to PDFs

✩

File Lists

slide-18
SLIDE 18

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

SQueaLer reports (continued)

⭑

Content by date thresholds

⭑

Parent Content

⭑

Unpublished Content

⭑

Content with documents

⭑

Paragraphs

⭑

Field Collections

⭑

Specific field values

⭑

Redirects

18

⭑

Metatag string queries:

✩

Description

✩

Abstract

✩

Token

✩

Creator

✩

Canonical

✩

Title

✩

Image

✩

Keyword

✩

Video

✩

Twitter

✩

Open Graph

slide-19
SLIDE 19

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

SQueaLer command

$ drush @[SITENAME].[ENVIRONMENT] squeal

19

/sites/[SITENAME].georgia.gov/files/ga_squealer_reports/ [SITENAME].georgia.gov_YYYY-MM-DD.xlsx

slide-20
SLIDE 20

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

20
slide-21
SLIDE 21

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

https://www.drupal.org/project/squealer

21
slide-22
SLIDE 22

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

22

Photo by chuttersnap on Unsplash

Strategies and Workflow

slide-23
SLIDE 23

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Did not migrate

⭑

Structural elements:

✩

Content types and field definitions

✩

Vocabularies

✩

Paragraph and field collection bundles

⭑

Views

⭑

Webform submissions

❌

Migrated

⭑

Data elements:

✩

Select nodes and field data

✩

Select taxonomy terms

⭑

Menus

⭑

Webforms

⭑

Files

23

✅

slide-24
SLIDE 24

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0 ⭑

Core:

✩

Migrate migrate

✩

Migrate Drupal migrate_drupal

⭑

Custom:

✩

ga_migrate

✩

ga_migrate_site

✩

ga_migrate_source_ui

24

Migration modules

⭑

Contributed:

✩

Migrate Files (extended) migrate_file

✩

Migrate Plus migrate_plus

✩

Migrate Source CSV migrate_source_csv

✩

Migrate Tools migrate_tools

✩

Drupal Upgrade migrate_upgrade

✩

Migrate Source UI migrate_source_ui

slide-25
SLIDE 25

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Development tools

⭑

Local development environment:

✩

Lando

⭑

QA environment:

✩

Tugboat.qa

⭑

DevOps magic:

✩

CircleCI

✩

Quay.io

25
slide-26
SLIDE 26

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

26

https://tugboat.qa

slide-27
SLIDE 27

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Development workflow

⭑

Focus on field mapping by complexity/content type:

✩

Basic fields

✩

Rich fields

✩

File/image fields

✩

Paragraphs/Field Collections

✩

WYSIWYG cleanup

27
slide-28
SLIDE 28

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Migration development strategy

⭑

Create/edit migration configuration files directly in config sync directory

⭑

Preserve nids for standalone nodes

⭑

Migrate unpublished content

⭑

Prioritize ability to rollback and re-import

⭑

Use ga_migrate_site for site specific overrides

⭑

Log skips and exceptions using custom logging solution

⭑

Solution order:

✩

Configuration, core and contrib

✩

Custom source/process plugins and services in ga_migrate module

✩

hook_migrate_MIGRATION_ID_prepare_row()

28
slide-29
SLIDE 29

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

29

Photo by Dorelys Smits on Unsplash

Custom Logging

slide-30
SLIDE 30

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

ga_migrate_log( $message, // String: detailed message with ids. $migration_id, // String: current migration id. $audience, // String: 'DSGa' or 'dev'. $needs_fix, // Boolean: Does this need to be fixed. $severity, // String: 'warning', 'notice', or 'error'. $category, // String: Short descriptor. $row_id // Integer: The current row id. );

30
slide-31
SLIDE 31

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

31
slide-32
SLIDE 32

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

32

Photo by Farzad Mohsenvand on Unsplash

Migration Phases

slide-33
SLIDE 33

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Migration phases

⭑

Add/remove sites from Tugboat

⭑

Run migrations on Tugboat

⭑

Client QA's migrations on Tugboat

⭑

Development team fixes issues

⭑

Run migration on Production

⭑

Client prepares sites for launch

⭑

Sites are launched

33
slide-34
SLIDE 34

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

34

Magical Nerdery

slide-35
SLIDE 35

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

35

Photo by James Wheeler from Pexels

Site Specific Overrides

slide-36
SLIDE 36

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

36

/modules/custom/ga_migrate_site /sites/[SITENAME].georgia.gov/modules/custom/ga_migrate_site

slide-37
SLIDE 37

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... ga_migrate: 0 ga_migrate_site: 0 ...

37

core.extension.yml

slide-38
SLIDE 38

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

interface GaMigrateSiteInterface { // Press_release nodes with release date greater // than threshold are trashed. const GA_MIGRATE_SITE_PRESS_RELEASE_THRESHOLD = 3; // The date unit that accompanies the threshold value. const GA_MIGRATE_SITE_PRESS_RELEASE_THRESHOLD_UNIT = 'y'; // The site node skip list. const GA_MIGRATE_SITE_SKIP_LIST = []; }

38

/modules/custom/ga_migrate_site/src/Plugin/GaMigrateSiteInterface.php

slide-39
SLIDE 39

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

// Implements hook_migrate_prepare_row(). // Implements hook_migrate_MIGRATION_ID_prepare_row().

39

/sites/[SITENAME].georgia.gov/modules/custom/ga_migrate_site/ga_migrate_site.module

slide-40
SLIDE 40

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

40

Photo by Victor Larracuente on Unsplash

Nested Paragraphs

slide-41
SLIDE 41

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

41

Container Paragraphs

slide-42
SLIDE 42

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

42

Content Paragraphs Container Paragraphs

slide-43
SLIDE 43

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

node

43

field_content two_column

  • ne_column

gta_paragraph_related_links gta_paragraph_image gta_paragraph_text_area

slide-44
SLIDE 44

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Paragraphs strategy

⭑

Convert Paragraphs into to Drupal 8 markup

✩

Includes entity embeds

⭑

Stack new content in Body field

44
slide-45
SLIDE 45

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

45

... prepared_field_content: plugin: ga_micro_content_to_text source:

  • field_content

micro_content: field_content: paragraphs_item ...

slide-46
SLIDE 46

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

What do you mean by "render"?

⭑

What should the Drupal 8 markup be for this paragraph when placed in the WYSIWYG Body field?

✩

Text markup

✩

Entity embed code

✩

File download link

✩

Alignment adjustments

46
slide-47
SLIDE 47

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

node

47

field_content two_column

  • ne_column

gta_paragraph_related_links gta_paragraph_image gta_paragraph_text_area

1 2 3 4 5 6

slide-48
SLIDE 48

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... body/0/value: plugin: concat source:

  • '@prepared_field_content'
  • body/0/value

...

48
slide-49
SLIDE 49

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

49

Photo by Anita Austvika on Unsplash

Circular Dependencies

slide-50
SLIDE 50

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

site_page node

50

field_related_links Link Node reference Node reference Link Link link_collection node field_rich_links Link Node reference Node reference Link Link

ga_d7_site_page_field_related_links

slide-51
SLIDE 51

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

site_page node

51

link_collection node topic_page node body nid entity embed code

ga_d7_node_site_page

slide-52
SLIDE 52

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... prepared_field_related_links:

  • plugin: migration_lookup

migration: ga_d7_site_page_field_related_links source: nid no_stub: true

  • plugin: ga_entity_embed_code

entity_type: node ...

52

ga_d7_node_site_page

slide-53
SLIDE 53

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... body/0/value:

  • plugin: concat

source:

  • body/0/value
  • '@prepared_field_related_links'

...

53

ga_d7_node_site_page

slide-54
SLIDE 54

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Dependencies

⭑

ga_d7_node_site_page

✩

ga_d7_site_page_field_related_links

54

฀฀ ฀฀

slide-55
SLIDE 55

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

site_page node

55

field_related_links Link blog_post reference site_page reference Link Link link_collection node field_rich_links Link blog_post reference NULL Link Link

ga_d7_site_page_field_related_links

slide-56
SLIDE 56

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... site_page_stub_entity_references: plugin: sub_process source: field_related_links process: entity_references: ...

  • plugin: migration_lookup

migration: ga_d7_node_site_page source: field_related_content/0/nid stub_id: ga_d7_node_site_page ...

56
slide-57
SLIDE 57

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

site_page node

57

field_related_links Link blog_post reference site_page reference Link Link link_collection node field_rich_links Link blog_post reference topic_page reference Link Link

ga_d7_site_page_field_related_links

slide-58
SLIDE 58

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... site_page_stub_entity_references: plugin: sub_process source: field_related_links process: entity_references: ...

  • plugin: migration_lookup

migration: ga_d7_node_site_page source: field_related_content/0/nid stub_id: ga_d7_node_site_page ...

58
slide-59
SLIDE 59

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Dependencies

⭑

ga_d7_node_site_page

✩

ga_d7_site_page_field_related_links

⭑

ga_d7_site_page_field_related_links

✩

ga_d7_node_blog_post

✩

"ga_d7_node_site_page"

59

฀฀ ฀฀ ฀฀ ฀฀ ฀฀

slide-60
SLIDE 60

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

It works if...

⭑

The non-specified dependency migration id is alphabetically before the current migration:

✩

ga_d7_node_site_page

✩

ga_d7_site_page_field_related_links

60
slide-61
SLIDE 61

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

It doesn't work if...

⭑

The non-specified dependency migration id is alphabetically afuer the current migration:

✩

ga_d7_index_list_field_related_links

✩

ga_d7_node_index_list

⭑

The fix hack:

✩

ga_d7_1_node_index_list

✩

ga_d7_index_list_field_related_links

⭑

Migration Dependency When Stubbing Content: https://www.drupal.org/project/drupal/issues/3024634

61
slide-62
SLIDE 62

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

62

Photo by Iker Urteaga on Unsplash

WYSIWYG DOM Processing

slide-63
SLIDE 63

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

... body/0/value: ...

  • plugin: dom

method: import

  • plugin: ga_wysiwyg_cleanup_dom

text_format: expanded

  • plugin: dom

method: export ...

63
slide-64
SLIDE 64

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

64

\DOMDocument

Xdebug

slide-65
SLIDE 65

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

\DOMDocument processing

⭑

Get elements from the \DOMDocument object.

⭑

Loop and collect the items to alter, replace, or remove in an array.

⭑

Loop through collection array and alter, replace or remove each element.

65
slide-66
SLIDE 66

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

// Get elements by tag. $elements = $dom->getElementsByTagName('*'); $remove_elements = []; if ($elements->length > 0) { foreach ($elements as $element) { // Collect elements based on conditions. $remove_elements[] = $element; } } // Remove or replace elements. foreach ($remove_elements as $element) { $this->removeElementAndContent($element); }

66
slide-67
SLIDE 67

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

WYSIWYG clean up

⭑

D7 embedded entity → D8 embed syntax

⭑

D7 <img> tag → D8 embedded media entity

⭑

D7 link to file → D8 file download link

⭑

D7 <iframe> tag → D8 embedded Code Block node or media entity

⭑

General text filtering based on D8 field text format

67
slide-68
SLIDE 68

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

68

We made it! 👐

slide-69
SLIDE 69

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

More about the Georgia.gov project

69

⭑

Georgia GovHub: a case study by Darren Peterson at Drupal GovCon 2019

✩

This is also coming to DrupalCon Minneapolis 2020!

⭑

A forest of designs without subthemes: Implementing Georgia.gov's front-end in Drupal 8 by Marc Drummond at Drupal GovCon 2019

slide-70
SLIDE 70

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

More about migration from Lullabot

70

⭑

Real Life Data Migrations on the Lullabot Podcast

⭑

An Overview for Migrating Drupal Sites to 8 by Juampy NR

⭑

Running and Testing Drupal 8 Migrations in CircleCI by Juampy NR

⭑

31 Days of Drupal Migrations with Mauricio Dinarte on the Lullabot Podcast

⭑

Managing Authentication During API Migrations by April Sides

⭑

and more to come!

slide-71
SLIDE 71

G E O R G I A G O V H U B M I G R A T I O N + F L O R I D A D C 2 0 2 0

Thank you.

71