README.md 13.1 KB
Newer Older
martin_klima's avatar
martin_klima committed
1
# Default content deploy
jakubhnilicka's avatar
jakubhnilicka committed
2 3 4
A default content deploy solution for Drupal 8.


martin_klima's avatar
martin_klima committed
5 6 7 8 9 10 11 12 13
- Introduction
- Requirements
- Install
- Configuration
- Drush commands
- Workflow - how to export and deploy content
- Protecting exported content data files
- Maintainers
- Sponsor
jakubhnilicka's avatar
jakubhnilicka committed
14 15


martin_klima's avatar
martin_klima committed
16
# Introduction
jakubhnilicka's avatar
jakubhnilicka committed
17

18 19 20 21 22
This module (DCD) provides content deployment and allows development
and building sites without the need to transfer database between the sites.
The development team can export and deploy all content via Git and content
can be deployed to the staging servers automatically during common deploy
processes. Module provides useful drush commands for export/import content.
23
Import function can also be ran from administration interface.
jakubhnilicka's avatar
jakubhnilicka committed
24

martin_klima's avatar
martin_klima committed
25
# Requirements
jakubhnilicka's avatar
jakubhnilicka committed
26

martin_klima's avatar
martin_klima committed
27
## Modules
28
- Default Content for Drupal 8 (**default_content**) -
martin_klima's avatar
martin_klima committed
29
https://www.drupal.org/project/default_content
30
- optionally **File entity** (file_entity)
31
  or **Better Normalizers** (better_normalizers) - if you need to deploy files,
32 33
  f.e. images, attachments.
https://www.drupal.org/project/file_entity,
34
https://github.com/drupal-media/file_entity,
35
https://www.drupal.org/project/better_normalizers
jakubhnilicka's avatar
jakubhnilicka committed
36

martin_klima's avatar
martin_klima committed
37
## Sites config synchronization (optional)
38

39
If you are sure the export and import sites have the same configuration and you
40 41
need to synchronize only content, you can skip this chapter.

42 43
You need identical site UUID for successful syncing configuration between sites.
If you need to sychronize configuration, use drush **config-set**
44
for set Site UUID to identical value.
jakubhnilicka's avatar
jakubhnilicka committed
45

martin_klima's avatar
martin_klima committed
46
**Example**
Michal Landsman's avatar
Michal Landsman committed
47

martin_klima's avatar
martin_klima committed
48
    drush config-set "system.site" uuid 11111111-1111-1111-1111-111111111111
martin_klima's avatar
martin_klima committed
49

50 51 52 53 54 55 56 57
The best practice is to install a drush site from already existing configuration,
e.g.:

for Drupal 8.5-

    drush si minimal --config-dir=../config/sync

for Drupal 8.6+
58

59 60
    drush si minimal --existing-config

martin_klima's avatar
martin_klima committed
61

martin_klima's avatar
martin_klima committed
62
# Install
martin_klima's avatar
martin_klima committed
63

64
* with composer
jakubhnilicka's avatar
jakubhnilicka committed
65

Michal Landsman's avatar
Michal Landsman committed
66
        composer require drupal/default_content_deploy
67

68
* with drush
69 70

        drush en default_content_deploy
jakubhnilicka's avatar
jakubhnilicka committed
71

martin_klima's avatar
martin_klima committed
72
# Configuration
jakubhnilicka's avatar
jakubhnilicka committed
73

74
Set DCD content directory in settings.php. We recommend to place directory
miroslav-lee's avatar
miroslav-lee committed
75
outside of the document root.
jakubhnilicka's avatar
jakubhnilicka committed
76

martin_klima's avatar
martin_klima committed
77 78
**Example**

79 80 81 82
    // Relative path.
    $settings['default_content_deploy_content_directory'] = '../content';
    // Absolute path.
    $settings['default_content_deploy_content_directory'] = '/var/dcd/content';
martin_klima's avatar
martin_klima committed
83

miroslav-lee's avatar
miroslav-lee committed
84 85 86

You can also do this on the `/admin/config/development/dcd` page.

martin_klima's avatar
martin_klima committed
87 88
# Drush commands

89 90
Module provides many useful shortcuts for export content and one very important
command for deploy content. You can export only one entity, bunch of entities,
91
entities by type or export whole site at once.
martin_klima's avatar
martin_klima committed
92

93 94
If a wrong content entity type is entered, module displays a list of all content
entity types available on the site as hint.
95

96
## drush default-content-deploy:export, drush dcde
martin_klima's avatar
martin_klima committed
97 98 99

Exports a single entity or group of entities with no references.

martin_klima's avatar
martin_klima committed
100
### Arguments
martin_klima's avatar
martin_klima committed
101

miroslav-lee's avatar
miroslav-lee committed
102
* **entity_type** - Entity type (e.g. node, user, taxonomy_term,
103
  custom_entity_type...)
martin_klima's avatar
martin_klima committed
104

martin_klima's avatar
martin_klima committed
105
### Options
martin_klima's avatar
martin_klima committed
106 107 108
* **entity_id** - ID of entity for export.
* **bundle** - Entity bundle, e.g. content type for nodes.
* **skip_entities** - ID of entity to skip.
miroslav-lee's avatar
miroslav-lee committed
109 110
* **force-update** - Deletes configurations files that are not used on the site.
* **folder** - Path to the export folder.
martin_klima's avatar
martin_klima committed
111

martin_klima's avatar
martin_klima committed
112
### Examples
martin_klima's avatar
martin_klima committed
113

114 115 116
    drush dcde node
Export all nodes.

117 118 119
    drush dcde node --folder='../content'
Export all nodes from the specified folder.

martin_klima's avatar
martin_klima committed
120
    drush dcde node --bundle=page
121
Export all nodes with bundle (content type) page.
122

martin_klima's avatar
martin_klima committed
123
    drush dcde node --bundle=page,article --entity_id=2,3,4
124
Export all nodes with bundle page or article plus nodes
125
with entity id 2, 3 and 4.
126

martin_klima's avatar
martin_klima committed
127
    drush dcde node --bundle=page,article --skip_entities=5,7
128
Export all nodes with bundle page or article and skip nodes
129
with entity id 5 and 7.
130

martin_klima's avatar
martin_klima committed
131
    drush dcde node --skip_entities=5,7
132
Export all nodes and skip nodes with entity id 5 and 7.
133

134
## drush default-content-deploy:export-with-references, drush dcder
martin_klima's avatar
martin_klima committed
135

136 137
Exports a single entity or group of entities with all references.

138
If a wrong content entity type is entered, module displays a list of all content
139
entity types available on the site as hint.
140

141
The options are identical in drush dcde.
martin_klima's avatar
martin_klima committed
142

martin_klima's avatar
martin_klima committed
143
### Arguments
martin_klima's avatar
martin_klima committed
144 145 146

* **entity_type** - Entity type (e.g. node, user, taxonomy/term…)

martin_klima's avatar
martin_klima committed
147
### Options
martin_klima's avatar
martin_klima committed
148 149 150 151

* **entity_id** - ID of entity for export.
* **bundle** - Entity bundle, e.g. content type for nodes.
* **skip_entities** - ID of entity to skip.
miroslav-lee's avatar
miroslav-lee committed
152 153
* **force-update** - Deletes configurations files that are not used on the site.
* **folder** - Path to the export folder.
martin_klima's avatar
martin_klima committed
154 155 156 157

**Examples**

    drush dcder node
158
Export all nodes with references
159 160 161 162

    drush dcder node --folder='../content'
Export all nodes with references from the specified folder

martin_klima's avatar
martin_klima committed
163
    drush dcder node --bundle=page
164
Export all nodes with references with bundle page
165

martin_klima's avatar
martin_klima committed
166
    drush dcder node --bundle=page,article --entity_id=2,3,4
167
Export all nodes with references with bundle page or article plus nodes
168
with entitiy id 2, 3 and 4.
169

martin_klima's avatar
martin_klima committed
170
    drush dcder node --bundle=page,article --skip_entities=5,7
171
Export all nodes with references with bundle page or article and skip nodes
172
with entity id 5 and 7.
173

martin_klima's avatar
martin_klima committed
174
    drush dcder node --skip_entities=5,7
175
Export all nodes and skip nodes with references with entity id 5 and 7.
jakubhnilicka's avatar
jakubhnilicka committed
176

martin_klima's avatar
martin_klima committed
177

178
## drush default-content-deploy:export-site, drush dcdes
jakubhnilicka's avatar
jakubhnilicka committed
179

180
Exports a whole site content + path aliases. You can exclude entities
181 182
by their type. Use 'drush dcd-entity-list' for list of all content entities
on this system.
jakubhnilicka's avatar
jakubhnilicka committed
183

martin_klima's avatar
martin_klima committed
184
### Options
martin_klima's avatar
martin_klima committed
185

martin_klima's avatar
martin_klima committed
186
* **skip_entity_type** - entity types to exclude from export.
miroslav-lee's avatar
miroslav-lee committed
187 188
* **force-update** - Deletes configurations files that are not used on the site.
* **folder** - Path to the export folder.
martin_klima's avatar
martin_klima committed
189

martin_klima's avatar
martin_klima committed
190 191 192
**Examples**

    drush dcdes
193
Export complete website.
194

martin_klima's avatar
martin_klima committed
195
    drush dcdes --skip_entity_type=node,user
196
Export complete website but skip nodes and users.
martin_klima's avatar
martin_klima committed
197

miroslav-lee's avatar
miroslav-lee committed
198 199
    drush dcdes --folder='../content'
Export complete website but from the specified folder
martin_klima's avatar
martin_klima committed
200

201
## drush default-content-deploy:import, drush dcdi
martin_klima's avatar
martin_klima committed
202

203
Deploy (import/create/update/replace) content from all exported files.
martin_klima's avatar
martin_klima committed
204

205
JSON files with exported content is expected in the directory defined
miroslav-lee's avatar
miroslav-lee committed
206
in **$settings['default_content_deploy_content_directory']** or on the administrative page. It can be defined in the **settings.php**.
martin_klima's avatar
martin_klima committed
207 208 209
See example in the Configuration section above.


martin_klima's avatar
martin_klima committed
210
### Important rules for import content
martin_klima's avatar
martin_klima committed
211

212
- Imported entity is determined by UUID (it can be either new or already
213
  existing).
miroslav-lee's avatar
miroslav-lee committed
214 215
- ID of entity is preserved, so the entity can not change its ID.
- Non-existing entity (the new one) is created with a new ID.
216
- Existing entity is updated only if imported entity is newer
martin_klima's avatar
martin_klima committed
217
  (by timestamp of the last entity change).
218
- Imported entity with the same or older time
219
  than the current existing entity is skipped.
220
- If a file entity does not have an existing file, the file will be created.
miroslav-lee's avatar
miroslav-lee committed
221
  The file will be recreated even if there is an existing file entity,
222
  but its file has been deleted.
223
- This behavior can be changed by parameter *--force-update*
miroslav-lee's avatar
miroslav-lee committed
224
  or *--force-override*. See an Example section.
225

226 227 228 229
***drush dcdi --force-override***

- All existing content will be overridden. Locally updated default content
will be reverted to the state defined in a content directory.
martin_klima's avatar
martin_klima committed
230

miroslav-lee's avatar
miroslav-lee committed
231 232 233 234
***drush dcdi --folder***

- All content will be imported from this folder.

martin_klima's avatar
martin_klima committed
235
***drush dcdi --verbose***
236 237

- Print detailed information about importing entities.
martin_klima's avatar
martin_klima committed
238

martin_klima's avatar
martin_klima committed
239
**Examples**
martin_klima's avatar
martin_klima committed
240 241

    drush dcdi
242
    drush dcdi --folder='../content'
miroslav-lee's avatar
miroslav-lee committed
243 244
    drush dcdi --force-override
    drush dcdi --force-override --folder='../content'
martin_klima's avatar
martin_klima committed
245

246
## drush default-content-deploy:uuid-info, drush dcd-uuid-info
martin_klima's avatar
martin_klima committed
247

248
Display UUID value of Entity.
martin_klima's avatar
martin_klima committed
249 250

**Example**
jakubhnilicka's avatar
jakubhnilicka committed
251

252
    drush dcd-uuid-info node 1
jakubhnilicka's avatar
jakubhnilicka committed
253 254


255 256 257 258 259 260 261 262
## drush default-content-deploy:entity-list, drush dcd-entity-list

Displays all current content entity types.

**Example**

    drush dcd-entity-list

miroslav-lee's avatar
miroslav-lee committed
263 264 265 266 267 268 269 270 271 272
# GUI

## Settings
Go to the `/admin/config/development/dcd` page.

## Export
Go to the `/admin/config/development/dcd/export` page.

## Import
Go to the `/admin/config/development/dcd/import` page.
273

jakubhnilicka's avatar
jakubhnilicka committed
274

martin_klima's avatar
martin_klima committed
275
# Team workflow - how to synchronize configuration and content between sites
jakubhnilicka's avatar
jakubhnilicka committed
276

277 278 279 280 281
Even though the DCD module does not necessarily require that the sites have
identical site UUID, it is logical that transferring entities from one site to
another requires identical configuration of entities (e.g. identical fields in
identically named bundles). That is why we include configuration synchronization
to the teamworkflow.
jakubhnilicka's avatar
jakubhnilicka committed
282

283
There are many articles about export/import configuration, so this is only a
martin_klima's avatar
martin_klima committed
284
sumarization of the most important things.
jakubhnilicka's avatar
jakubhnilicka committed
285

martin_klima's avatar
martin_klima committed
286
## Initiate project and Synchronize site configurations
jakubhnilicka's avatar
jakubhnilicka committed
287

288
**Developer 1 (first pusher)**
martin_klima's avatar
martin_klima committed
289 290 291 292

provides the first copy of a project. He must:

1. Create Drupal 8 project
293
2. Set identical information for the whole development team
martin_klima's avatar
martin_klima committed
294 295
   (e.g. save them to default.settings.php)
  1. Set identical directory for config management ($config_directories['sync'])
296
  2. Set identical directory for content export/import ($config['content'])
martin_klima's avatar
martin_klima committed
297
  3. Set identical file or value for Drupal salt ($settings['hash_salt']), e.g.:
298

martin_klima's avatar
martin_klima committed
299
         $settings['hash_salt'] = file_get_contents('../config/salt/salt.txt');
300

martin_klima's avatar
martin_klima committed
301
3. Install Drupal project (use the same installation profile, e.g. minimal)
302
4. Set (or get) Site UUID and share the value with the team.
303
   Identical Site UUID is neccessary for sharing Drupal configuration files.
304

martin_klima's avatar
martin_klima committed
305
        drush config-get "system.site" uuid
306

martin_klima's avatar
martin_klima committed
307
        drush config-set "system.site" uuid "112233…8899"
308 309

5. Install **Default Content Deploy** module and optionally the **File entity**
310
   module for exporting files like images.
martin_klima's avatar
martin_klima committed
311 312 313 314 315
6. Export configuration **drush cex**
7. Prepare team Git repository and push the project files into it.
8. Share necessary information with other developers.


316
**Developer 2 - n-th (pullers)**
martin_klima's avatar
martin_klima committed
317 318 319 320 321

install clones of the project. They must:

1. Clone project from the Git repository
2. Set identical information (identical setting in settings.php)
322
  1. Common directory for config management ($config_directories['sync'])
323
  2. Common directory for content export/import ($settings['default_content_deploy_content_directory'])
324
  3. Common file or value for Drupal salt ($settings['hash_salt'])
martin_klima's avatar
martin_klima committed
325 326
3. Install Drupal with the same installation profile
4. Set Site UUID to identical value.
327

martin_klima's avatar
martin_klima committed
328
        drush config-set "system.site" uuid "112233…8899"
329

martin_klima's avatar
martin_klima committed
330
5. Import configuration
331

martin_klima's avatar
martin_klima committed
332 333 334 335 336
        drush cim


## Export and import content

337 338 339 340
For successful syncing content between sites, you need to have identical UUIDs
for Admin user and Anonymous user (and for others users too if you have them).
These values will be synced automatically during DCD import process if the user
entities are exported, so we recommend to start exporting content with all
341
references.
martin_klima's avatar
martin_klima committed
342 343 344 345

**Developer pusher**

1. Creates some testing content
346
2. Export content. There are many ways to export content via drush,
347
   from one entity to the entire site (the easiest way).
348

martin_klima's avatar
martin_klima committed
349
        drush dcdes
350

martin_klima's avatar
martin_klima committed
351
3. Commit and push exported files to common Git repository
352

martin_klima's avatar
martin_klima committed
353 354 355 356 357 358
        git commit
        git push

**Developer puller**

1. Pull changes from the git repository
359

martin_klima's avatar
martin_klima committed
360 361 362
        git pull

2. Simply import content
363

miroslav-lee's avatar
miroslav-lee committed
364
        drush dcdi
martin_klima's avatar
martin_klima committed
365

366 367 368 369 370
  This command warns a user about entities in conflict.
  You can use **--verbose** option (**-v**) for more detailed information.
  We recomend more aggressive way which ensures that all content entities
  will be synchronized with the source. This option also rewrites already
  created content and updates UUID for core user entity. See detailed
martin_klima's avatar
martin_klima committed
371
  explanation in the **Important Import rules**.
372

martin_klima's avatar
martin_klima committed
373 374 375 376 377 378 379 380 381 382 383 384 385 386
## Common team workflow

**Developer pusher**

    1. drush cex
    2. drush dcdes
    3. git commit
    4. git push

**Developer puller**

    1. git pull
    2. drush updb
    4. drush cim
miroslav-lee's avatar
miroslav-lee committed
387
    5. drush dcdi
martin_klima's avatar
martin_klima committed
388 389


martin_klima's avatar
martin_klima committed
390
## Jenkins and tools for continous development / integration
martin_klima's avatar
martin_klima committed
391

392
Imagine Jenkins like one of the developers in the puller role but with
martin_klima's avatar
martin_klima committed
393 394 395 396 397 398
no interaction capability. His workflow can look like this:

    1. git pull
    2. drush updb -y
    3. drush cim -y
    4. drush cr
miroslav-lee's avatar
miroslav-lee committed
399
    5. drush dcdi -y
martin_klima's avatar
martin_klima committed
400 401 402 403


# Protecting exported content data files

404 405
We recommend placing the content directory outside of the document root,
so the exported content is well protected. In this case it will not be
406
accessible from the web server.
martin_klima's avatar
martin_klima committed
407

408 409 410
If this is not possible, it could result in a security problem.
Should any attacker know the UUID of desired content and also where it is
stored, then he could determine the URL to obtain the desired content without
411
permission.
martin_klima's avatar
martin_klima committed
412

413
Example of attacker’s URL:
martin_klima's avatar
martin_klima committed
414 415 416 417 418 419

    http://example.com/dcd_content_dir/node/uuid.json

**Secure content directory within docroot**

You can secure access to content directory via .htaccess or Nginx configuration.
jakubhnilicka's avatar
jakubhnilicka committed
420 421 422

Example for Nginx host config:

martin_klima's avatar
martin_klima committed
423
    location ~ .*/default_content_deploy_content/.*.json$ {
jakubhnilicka's avatar
jakubhnilicka committed
424 425 426
      return 403;
    }

martin_klima's avatar
martin_klima committed
427 428 429
Example of .htaccess for Apache host.

    Deny from all
jakubhnilicka's avatar
jakubhnilicka committed
430

martin_klima's avatar
martin_klima committed
431 432 433 434
Place .htaccess into content directory.


# Authors and maintainers
martin_klima's avatar
martin_klima committed
435 436
- Martin Klíma, https://www.drupal.org/u/martin_klima, martin.klima@hqis.cz
- Jakub Hnilička, https://www.drupal.org/u/hnilickajakub
martin_klima's avatar
martin_klima committed
437
- Radoslav Terezka, https://www.drupal.org/u/hideaway
438
- Miroslav Lee, https://www.drupal.org/u/miroslav-lee
jakubhnilicka's avatar
jakubhnilicka committed
439

martin_klima's avatar
martin_klima committed
440
# Sponsor
jakubhnilicka's avatar
jakubhnilicka committed
441
This project has been sponsored by:
martin_klima's avatar
martin_klima committed
442

martin_klima's avatar
martin_klima committed
443 444 445
HBF s.r.o., http://hbf.sk/, https://www.drupal.org/hbf

HBF provides flexible easy-to-use web solutions for your company.
446
Its mission is to help you run your business in online world with attractive
447
and perfectly working website.