contentful_bootstrap 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 707aaf25b774e94bc57a7a4fcbafca299a087c0b
4
- data.tar.gz: 931621f83a894b336f81fcd65b729dcd90c0e03f
3
+ metadata.gz: aed4d8f7790b4347e4b97050a049803f83ec1384
4
+ data.tar.gz: 91d3a12fd648ab548711294e39e9399bbb4c6e03
5
5
  SHA512:
6
- metadata.gz: 4c306b28133c2411c327b6ee266ad8ec04f9eaa1284dc40a82dd798b8c332f1571c856bd010c7ebb330e45696ef2f3bb483d9b1771e13bf8bca074edba074a90
7
- data.tar.gz: 20b2c92ab22e7b511fafb1cb9735e72a4fd8ec9ca0d37829d346245add717c80041dcc99594605dd72e1e4954a90ede31b5cb0110d4c372a7cba17f455e896a3
6
+ metadata.gz: a862d0a72856f0707f3ab2cd5920cef7484ea06b051cc308a6e03b45af3b60006dd86c86c4ffa23a9feaf8ed34e6811e813a24d5076bca28abe2d85e47ff2969
7
+ data.tar.gz: 31596e9e9211c8ec76daff969d3a79c2ea9aa6e7901ede6ab0b4b63ab7b1b4ecb7627664db8708c3841fc21fe425b96845a96a4eab0e43d519148fc0a5574faa
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v3.2.0
6
+ ### Added
7
+ * Adds `update_space` command to update already existing spaces using JSON Templates
8
+ * Adds `--mark-processed` option to `create_space` and `update_space` to enforce marking which resources have already been processed
9
+
5
10
  ## v3.1.1
6
11
  ### Fixed
7
12
  * Fixes a bug where `display_field` was not properly populated when being generated from JSON templates [#35](https://github.com/contentful/contentful-bootstrap.rb/issues/35)
data/README.md CHANGED
@@ -26,7 +26,7 @@ $ gem install contentful_bootstrap
26
26
  You can create spaces by doing:
27
27
 
28
28
  ```bash
29
- $ contentful_bootstrap create_space <space_name> [--template template_name] [--json-template template_path] [--config CONFIG_PATH]
29
+ $ contentful_bootstrap create_space <space_name> [--template template_name] [--json-template template_path] [--mark-processed] [--config CONFIG_PATH]
30
30
  ```
31
31
 
32
32
  You can also generate new Delivery API Tokens by doing:
@@ -41,6 +41,12 @@ You can also generate JSON Templates from existing spaces by doing:
41
41
  $ contentful_bootstrap generate_json <space_id> <access_token> [--output-file OUTPUT PATH]
42
42
  ```
43
43
 
44
+ You can update existing spaces from JSON Templates by doing:
45
+
46
+ ```bash
47
+ $ contentful_bootstrap update_space <space_id> -j template_path [--mark-processed]
48
+ ```
49
+
44
50
  ### Built-in templates
45
51
 
46
52
  Just getting started with Contentful? We have included the following built-in templates:
@@ -81,11 +87,23 @@ Additionally, you can send an options hash with the following keys:
81
87
  options = {
82
88
  template: "blog", # Will use one of the predefined templates and create Content Types, Assets and Entries
83
89
  json_template: "/path/to/template.json", # Will use the JSON file specified as a Template
90
+ mark_processed: false, # if true will mark all resources as 'bootstrapProcessed' and will be avoided for update_space calls (doesnt affect create_space)
84
91
  trigger_oauth: true # if true will trigger OAuth process
85
92
  }
86
93
  Contentful::Bootstrap::CommandRunner.new.create_space("space_name", options)
87
94
  ```
88
95
 
96
+ To Update an existing Space
97
+
98
+ ```ruby
99
+ options = {
100
+ json_template: "/path/to/template.json", # Will use the JSON file specified as a Template
101
+ mark_processed: false, # if true will mark all resources as 'bootstrapProcessed and will be avoided on future update_space calls
102
+ trigger_oauth: true # if true will trigger OAuth process
103
+ }
104
+ Contentful::Bootstrap::CommandRunner.new.update_space("space_id", options)
105
+ ```
106
+
89
107
  To Create a new Delivery API Token
90
108
 
91
109
  ```ruby
@@ -147,6 +165,9 @@ Using the `--json-template` option, you can create spaces with your own predefin
147
165
  This can be useful for creating testing & development spaces or just starting new projects from
148
166
  a common baseline. You can find a complete example [here](./examples/templates/catalogue.json)
149
167
 
168
+ Using the `--mark-processed` option alongside `--json-template` will mark all resources as `bootstrapProcessed`,
169
+ which will make it so `update_space` calls avoid already created resources. (A resource being either a Content Type, Entry or Asset).
170
+
150
171
  ## Contributing
151
172
 
152
173
  Feel free to improve this tool by submitting a Pull Request. For more information,
@@ -7,13 +7,31 @@ options = {}
7
7
 
8
8
  subcommands = {
9
9
  'create_space' => OptionParser.new do |opts|
10
- opts.banner = "Usage: create_space <space_name> [--template TEMPLATE_NAME] [--json-template JSON_PATH] [--config CONFIG_PATH]"
10
+ opts.banner = "Usage: create_space <space_name> [--template TEMPLATE_NAME] [--json-template JSON_PATH] [--mark-processed] [--config CONFIG_PATH]"
11
11
  opts.on("-t TEMPLATE", "--template TEMPLATE", "Specify Template", "Available Templates: blog, catalogue, gallery") do |t|
12
12
  options[:template] = t
13
13
  end
14
14
  opts.on("-j JSON_PATH", "--json-template JSON_PATH", "Specify JSON Template Path") do |j|
15
15
  options[:json_template] = j
16
16
  end
17
+ opts.on('-m', '--mark-processed', "Mark Processed Items on JSON Templates") do |m|
18
+ options[:mark_processed] = m
19
+ end
20
+ opts.on("-c CONFIG_PATH", "--config CONFIG_PATH", "Specify Configuration Path") do |c|
21
+ options[:config_path] = c
22
+ end
23
+ opts.on_tail("-h", "--help", "Print this message") do
24
+ puts opts
25
+ end
26
+ end,
27
+ 'update_space' => OptionParser.new do |opts|
28
+ opts.banner = "Usage: update_space <space_id> --json-template JSON_PATH [--mark-processed] [--config CONFIG_PATH]"
29
+ opts.on("-j JSON_PATH", "--json-template JSON_PATH", "Specify JSON Template Path") do |j|
30
+ options[:json_template] = j
31
+ end
32
+ opts.on('-m', '--mark-processed', "Mark Processed Items on JSON Templates") do |m|
33
+ options[:mark_processed] = m
34
+ end
17
35
  opts.on("-c CONFIG_PATH", "--config CONFIG_PATH", "Specify Configuration Path") do |c|
18
36
  options[:config_path] = c
19
37
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "content_types": [
3
+ "contentTypes": [
4
4
  {
5
5
  "id": "brand",
6
6
  "name": "Brand",
@@ -148,7 +148,7 @@
148
148
  "name": "Playsam, Inc",
149
149
  "website": "http://www.playsam.com",
150
150
  "logo": {
151
- "link_type": "Asset",
151
+ "linkType": "Asset",
152
152
  "id": "playsam_image"
153
153
  }
154
154
  }
@@ -14,10 +14,21 @@ module Contentful
14
14
  def create_space(space_name, options = {})
15
15
  template_name = options.fetch(:template, nil)
16
16
  json_template = options.fetch(:json_template, nil)
17
+ mark_processed = options.fetch(:mark_processed, false)
17
18
  trigger_oauth = options.fetch(:trigger_oauth, true)
18
19
 
19
20
  Contentful::Bootstrap::Commands::CreateSpace.new(
20
- @token, space_name, template_name, json_template, trigger_oauth
21
+ @token, space_name, template_name, json_template, mark_processed, trigger_oauth
22
+ ).run
23
+ end
24
+
25
+ def update_space(space_id, options = {})
26
+ json_template = options.fetch(:json_template, nil)
27
+ mark_processed = options.fetch(:mark_processed, false)
28
+ trigger_oauth = options.fetch(:trigger_oauth, true)
29
+
30
+ Contentful::Bootstrap::Commands::UpdateSpace.new(
31
+ @token, space_id, json_template, mark_processed, trigger_oauth
21
32
  ).run
22
33
  end
23
34
 
@@ -1,3 +1,4 @@
1
1
  require 'contentful/bootstrap/commands/create_space'
2
+ require 'contentful/bootstrap/commands/update_space'
2
3
  require 'contentful/bootstrap/commands/generate_token'
3
4
  require 'contentful/bootstrap/commands/generate_json'
@@ -9,10 +9,13 @@ module Contentful
9
9
  module Commands
10
10
  class CreateSpace < Base
11
11
  attr_reader :template_name, :json_template
12
- def initialize(token, space_name, template_name = nil, json_template = nil, trigger_oauth = true)
12
+ def initialize(
13
+ token, space_name, template_name = nil,
14
+ json_template = nil, mark_processed = false, trigger_oauth = true)
13
15
  super(token, space_name, trigger_oauth)
14
16
  @template_name = template_name
15
17
  @json_template = json_template
18
+ @mark_processed = mark_processed
16
19
  end
17
20
 
18
21
  def run
@@ -92,7 +95,7 @@ module Contentful
92
95
  def create_json_template(space)
93
96
  if ::File.exist?(@json_template)
94
97
  puts "Creating JSON Template '#{@json_template}'"
95
- Templates::JsonTemplate.new(space, @json_template).run
98
+ Templates::JsonTemplate.new(space, @json_template, @mark_processed).run
96
99
  puts "JSON Template '#{@json_template}' created!"
97
100
  else
98
101
  puts "JSON Template '#{@json_template}' does not exist. Please check that you specified the correct file name."
@@ -0,0 +1,59 @@
1
+ require 'contentful/management'
2
+ require 'contentful/management/error'
3
+ require 'contentful/bootstrap/templates'
4
+ require 'contentful/bootstrap/commands/base'
5
+
6
+ module Contentful
7
+ module Bootstrap
8
+ module Commands
9
+ class UpdateSpace < Base
10
+ attr_reader :json_template
11
+ def initialize(token, space_id, json_template = nil, mark_processed = false, trigger_oauth = true)
12
+ super(token, space_id, trigger_oauth)
13
+ @json_template = json_template
14
+ @mark_processed = mark_processed
15
+ end
16
+
17
+ def run
18
+ if @json_template.nil?
19
+ puts 'JSON Template not found. Exiting!'
20
+ exit(1)
21
+ end
22
+
23
+ puts "Updating Space '#{@space}'"
24
+
25
+ update_space = fetch_space
26
+
27
+ update_json_template(update_space)
28
+
29
+ puts
30
+ puts "Successfully updated Space #{@space}"
31
+
32
+ update_space
33
+ end
34
+
35
+ protected
36
+
37
+ def fetch_space
38
+ Contentful::Management::Space.find(@space)
39
+ rescue Contentful::Management::NotFound
40
+ puts 'Space Not Found. Exiting!'
41
+ exit(1)
42
+ end
43
+
44
+ private
45
+
46
+ def update_json_template(space)
47
+ if ::File.exist?(@json_template)
48
+ puts "Updating from JSON Template '#{@json_template}'"
49
+ Templates::JsonTemplate.new(space, @json_template, @mark_processed, false).run
50
+ puts "JSON Template '#{@json_template}' updated!"
51
+ else
52
+ puts "JSON Template '#{@json_template}' does not exist. Please check that you specified the correct file name."
53
+ exit(1)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -16,6 +16,8 @@ module Contentful
16
16
  create_content_types
17
17
  create_assets
18
18
  create_entries
19
+
20
+ after_run
19
21
  rescue Contentful::Management::Error => e
20
22
  error = e.error
21
23
  puts "Error at: #{error[:url]}"
@@ -37,6 +39,9 @@ module Contentful
37
39
  []
38
40
  end
39
41
 
42
+ def after_run
43
+ end
44
+
40
45
  protected
41
46
 
42
47
  def create_image(name, url)
@@ -51,34 +56,40 @@ module Contentful
51
56
 
52
57
  def create_content_types
53
58
  content_types.each do |ct|
54
- puts "Creating Content Type '#{ct['name']}'"
55
-
56
- fields = []
57
- content_type = space.content_types.new
58
- content_type.id = ct['id']
59
- content_type.name = ct['name']
60
- content_type.display_field = ct['display_field']
61
-
62
- ct['fields'].each do |f|
63
- field = Contentful::Management::Field.new
64
- field.id = f['id']
65
- field.name = f['name']
66
- field.type = f['type']
67
- field.link_type = f['linkType'] if link?(f)
68
-
69
- if array?(f)
70
- array_field = Contentful::Management::Field.new
71
- array_field.type = f['items']['type']
72
- array_field.link_type = f['items']['linkType']
73
- field.items = array_field
59
+ begin
60
+ puts "Creating Content Type '#{ct['name']}'"
61
+
62
+ fields = []
63
+ content_type = space.content_types.new
64
+ content_type.id = ct['id']
65
+ content_type.name = ct['name']
66
+ content_type.display_field = ct['display_field']
67
+ content_type.description = ct['description']
68
+
69
+ ct['fields'].each do |f|
70
+ field = Contentful::Management::Field.new
71
+ field.id = f['id']
72
+ field.name = f['name']
73
+ field.type = f['type']
74
+ field.link_type = f['linkType'] if link?(f)
75
+
76
+ if array?(f)
77
+ array_field = Contentful::Management::Field.new
78
+ array_field.type = f['items']['type']
79
+ array_field.link_type = f['items']['linkType']
80
+ field.items = array_field
81
+ end
82
+
83
+ fields << field
74
84
  end
75
85
 
76
- fields << field
86
+ content_type.fields = fields
87
+ content_type.save
88
+ content_type.activate
89
+ rescue Contentful::Management::Conflict
90
+ puts "ContentType '#{ct['id']}' already created! Skipping"
91
+ next
77
92
  end
78
-
79
- content_type.fields = fields
80
- content_type.save
81
- content_type.activate
82
93
  end
83
94
  end
84
95
 
@@ -92,23 +103,28 @@ module Contentful
92
103
 
93
104
  def create_assets
94
105
  assets.each do |asset|
95
- puts "Creating Asset '#{asset['title']}'"
96
- asset = space.assets.create(
97
- id: asset['id'],
98
- title: asset['title'],
99
- file: asset['file']
100
- )
101
- asset.process_file
102
-
103
- attempts = 0
104
- while attempts < 10
105
- unless space.assets.find(asset.id).file.url.nil?
106
- asset.publish
107
- break
108
- end
106
+ begin
107
+ puts "Creating Asset '#{asset['title']}'"
108
+ asset = space.assets.create(
109
+ id: asset['id'],
110
+ title: asset['title'],
111
+ file: asset['file']
112
+ )
113
+ asset.process_file
114
+
115
+ attempts = 0
116
+ while attempts < 10
117
+ unless space.assets.find(asset.id).file.url.nil?
118
+ asset.publish
119
+ break
120
+ end
109
121
 
110
- sleep(1) # Wait for Process
111
- attempts += 1
122
+ sleep(1) # Wait for Process
123
+ attempts += 1
124
+ end
125
+ rescue Contentful::Management::Conflict
126
+ puts "Asset '#{asset['id']}' already created! Skipping"
127
+ next
112
128
  end
113
129
  end
114
130
  end
@@ -150,17 +166,23 @@ module Contentful
150
166
  e[rf.to_sym] = value
151
167
  end
152
168
 
153
- entry = content_type.entries.create({:id => e[:id]})
154
- entry.save
155
-
156
- e = e.clone
157
- e[:id] = entry.id # in case no ID was specified in template
158
- e
169
+ begin
170
+ puts "Creating Entry #{e[:id]}"
171
+ entry = content_type.entries.create({:id => e[:id]})
172
+ entry.save
173
+
174
+ e = e.clone
175
+ e[:id] = entry.id # in case no ID was specified in template
176
+ rescue Contentful::Management::Conflict
177
+ puts "Entry '#{e[:id]}' already exists! Skipping"
178
+ ensure
179
+ next e
180
+ end
159
181
  end
160
182
  end.flatten
161
183
 
162
184
  processed_entries = processed_entries.map do |e|
163
- puts "Creating Entry #{e[:id]}"
185
+ puts "Populating Entry #{e[:id]}"
164
186
 
165
187
  entry = space.entries.find(e[:id])
166
188
  e.delete(:id)
@@ -169,7 +191,7 @@ module Contentful
169
191
 
170
192
  10.times do
171
193
  break if space.entries.find(entry.id).sys[:version] >= 4
172
- sleep(1)
194
+ sleep(0.5)
173
195
  end
174
196
 
175
197
  entry.id
@@ -6,31 +6,53 @@ module Contentful
6
6
  module Bootstrap
7
7
  module Templates
8
8
  class JsonTemplate < Base
9
- def initialize(space, file)
9
+ CONTENT_TYPES_KEY = 'contentTypes'
10
+ ENTRIES_KEY = 'entries'
11
+ ASSETS_KEY = 'assets'
12
+ BOOTSTRAP_PROCCESSED_KEY = 'bootstrapProcessed'
13
+ DISPLAY_FIELD_KEY = 'display_field'
14
+ ALTERNATE_DISPLAY_FIELD_KEY = 'displayField'
15
+ SYS_KEY = 'sys'
16
+
17
+ attr_reader :assets, :entries, :content_types
18
+
19
+ def initialize(space, file, mark_processed = false, all = true)
10
20
  @space = space
11
21
  @file = file
12
- @assets = nil
13
- @entries = nil
22
+ @all = all
23
+ @mark_processed = mark_processed
24
+
14
25
  json
15
26
 
27
+ @assets = process_assets
28
+ @entries = process_entries
29
+ @content_types = process_content_types
30
+
16
31
  check_version
17
32
  end
18
33
 
19
- def content_types
20
- processed_content_types = json.fetch('contentTypes', [])
21
- processed_content_types.each do |content_type|
22
- content_type['display_field'] = content_type.key?('displayField') ? content_type.delete('displayField') : content_type['display_field']
34
+ def after_run
35
+ return unless mark_processed?
36
+
37
+ @json.fetch(CONTENT_TYPES_KEY, []).each do |content_type|
38
+ content_type[BOOTSTRAP_PROCCESSED_KEY] = true
23
39
  end
24
40
 
25
- processed_content_types
26
- end
41
+ @json.fetch(ASSETS_KEY, []).each do |asset|
42
+ asset[BOOTSTRAP_PROCCESSED_KEY] = true
43
+ end
27
44
 
28
- def assets
29
- @assets ||= process_assets
30
- end
45
+ @json.fetch(ENTRIES_KEY, {}).each do |_content_type_name, entry_list|
46
+ entry_list.each do |entry|
47
+ if entry.key?(SYS_KEY)
48
+ entry[SYS_KEY][BOOTSTRAP_PROCCESSED_KEY] = true
49
+ else
50
+ entry[SYS_KEY] = { BOOTSTRAP_PROCCESSED_KEY => true }
51
+ end
52
+ end
53
+ end
31
54
 
32
- def entries
33
- @entries ||= process_entries
55
+ ::File.write(@file, JSON.pretty_generate(@json))
34
56
  end
35
57
 
36
58
  private
@@ -45,10 +67,36 @@ module Contentful
45
67
 
46
68
  def json
47
69
  @json ||= ::JSON.parse(::File.read(@file))
70
+ rescue
71
+ puts 'File is not JSON. Exiting!'
72
+ exit(1)
73
+ end
74
+
75
+ def process_content_types
76
+ processed_content_types = json.fetch(CONTENT_TYPES_KEY, [])
77
+
78
+ unless all?
79
+ processed_content_types = processed_content_types.select do |content_type|
80
+ !content_type.fetch(BOOTSTRAP_PROCCESSED_KEY, false)
81
+ end
82
+ end
83
+
84
+ processed_content_types.each do |content_type|
85
+ content_type[DISPLAY_FIELD_KEY] = content_type.key?(ALTERNATE_DISPLAY_FIELD_KEY) ? content_type.delete(ALTERNATE_DISPLAY_FIELD_KEY) : content_type[DISPLAY_FIELD_KEY]
86
+ end
87
+
88
+ processed_content_types
48
89
  end
49
90
 
50
91
  def process_assets
51
- unprocessed_assets = json.fetch('assets', [])
92
+ unprocessed_assets = json.fetch(ASSETS_KEY, [])
93
+
94
+ unless all?
95
+ unprocessed_assets = unprocessed_assets.select do |asset|
96
+ !asset.fetch(BOOTSTRAP_PROCCESSED_KEY, false)
97
+ end
98
+ end
99
+
52
100
  unprocessed_assets.map do |asset|
53
101
  asset['file'] = create_image(
54
102
  asset['file']['filename'],
@@ -60,15 +108,22 @@ module Contentful
60
108
 
61
109
  def process_entries
62
110
  processed_entries = {}
63
- unprocessed_entries = json.fetch('entries', {})
111
+ unprocessed_entries = json.fetch(ENTRIES_KEY, {})
64
112
  unprocessed_entries.each do |content_type_id, entry_list|
65
113
  entries_for_content_type = []
114
+
115
+ unless all?
116
+ entry_list = entry_list.select do |entry|
117
+ !entry[SYS_KEY].fetch(BOOTSTRAP_PROCCESSED_KEY, false)
118
+ end
119
+ end
120
+
66
121
  entry_list.each do |entry|
67
122
  processed_entry = {}
68
123
  array_fields = []
69
124
  link_fields = []
70
125
 
71
- processed_entry['id'] = entry['sys']['id'] if entry.key?('sys') && entry['sys'].key?('id')
126
+ processed_entry['id'] = entry[SYS_KEY]['id'] if entry.key?(SYS_KEY) && entry[SYS_KEY].key?('id')
72
127
 
73
128
  entry.fetch('fields', {}).each do |field, value|
74
129
  link_fields << field if value.is_a? ::Hash
@@ -108,6 +163,14 @@ module Contentful
108
163
  Contentful::Bootstrap::Templates::Links::Asset.new(id)
109
164
  end
110
165
  end
166
+
167
+ def all?
168
+ @all
169
+ end
170
+
171
+ def mark_processed?
172
+ @mark_processed
173
+ end
111
174
  end
112
175
  end
113
176
  end
@@ -1,6 +1,6 @@
1
1
  module Contentful
2
2
  module Bootstrap
3
- VERSION = '3.1.1'
3
+ VERSION = '3.2.0'
4
4
 
5
5
  def self.major_version
6
6
  VERSION.split('.').first.to_i
@@ -5,8 +5,6 @@ describe Contentful::Bootstrap::CommandRunner do
5
5
  subject { Contentful::Bootstrap::CommandRunner.new(path) }
6
6
 
7
7
  describe 'instance methods' do
8
- before do
9
- end
10
8
  describe '#create_space' do
11
9
  before do
12
10
  allow_any_instance_of(Contentful::Bootstrap::Commands::CreateSpace).to receive(:run)
@@ -14,7 +12,7 @@ describe Contentful::Bootstrap::CommandRunner do
14
12
 
15
13
  it 'default values' do
16
14
  expect(Contentful::Bootstrap::Commands::CreateSpace).to receive(:new).with(
17
- subject.token, 'foo', nil, nil, true
15
+ subject.token, 'foo', nil, nil, false, true
18
16
  ).and_call_original
19
17
 
20
18
  subject.create_space('foo')
@@ -22,10 +20,10 @@ describe Contentful::Bootstrap::CommandRunner do
22
20
 
23
21
  it 'with options' do
24
22
  expect(Contentful::Bootstrap::Commands::CreateSpace).to receive(:new).with(
25
- subject.token, 'foo', 'bar', 'baz', false
23
+ subject.token, 'foo', 'bar', 'baz', true, false
26
24
  ).and_call_original
27
25
 
28
- subject.create_space('foo', template: 'bar', json_template: 'baz', trigger_oauth: false)
26
+ subject.create_space('foo', template: 'bar', json_template: 'baz', mark_processed: true, trigger_oauth: false)
29
27
  end
30
28
 
31
29
  it 'runs command' do
@@ -35,6 +33,34 @@ describe Contentful::Bootstrap::CommandRunner do
35
33
  end
36
34
  end
37
35
 
36
+ describe '#update_space' do
37
+ before do
38
+ allow_any_instance_of(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:run)
39
+ end
40
+
41
+ it 'default values' do
42
+ expect(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:new).with(
43
+ subject.token, 'foo', nil, false, true
44
+ ).and_call_original
45
+
46
+ subject.update_space('foo')
47
+ end
48
+
49
+ it 'with options' do
50
+ expect(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:new).with(
51
+ subject.token, 'foo', 'bar', true, false
52
+ ).and_call_original
53
+
54
+ subject.update_space('foo', json_template: 'bar', mark_processed: true, trigger_oauth: false)
55
+ end
56
+
57
+ it 'runs command' do
58
+ expect_any_instance_of(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:run)
59
+
60
+ subject.update_space('foo', json_template: 'bar', trigger_oauth: false)
61
+ end
62
+ end
63
+
38
64
  describe '#generate_token' do
39
65
  before do
40
66
  allow_any_instance_of(Contentful::Bootstrap::Commands::GenerateToken).to receive(:run)
@@ -3,9 +3,13 @@ require 'spec_helper'
3
3
  describe Contentful::Bootstrap::Commands::CreateSpace do
4
4
  let(:path) { File.expand_path(File.join('spec', 'fixtures', 'ini_fixtures', 'contentfulrc.ini')) }
5
5
  let(:token) { Contentful::Bootstrap::Token.new path }
6
- subject { Contentful::Bootstrap::Commands::CreateSpace.new token, 'foo', 'bar', 'baz', false }
6
+ subject { Contentful::Bootstrap::Commands::CreateSpace.new token, 'foo', 'bar', 'baz', false, false }
7
7
  let(:space_double) { SpaceDouble.new }
8
8
 
9
+ before do
10
+ allow(::File).to receive(:write)
11
+ end
12
+
9
13
  describe 'instance methods' do
10
14
  describe '#run' do
11
15
  it 'with all non nil attributes' do
@@ -18,7 +22,7 @@ describe Contentful::Bootstrap::Commands::CreateSpace do
18
22
  end
19
23
 
20
24
  it 'does not create template when template_name is nil' do
21
- create_space_command = described_class.new(token, 'foo', nil, 'baz', false)
25
+ create_space_command = described_class.new(token, 'foo', nil, 'baz', false, false)
22
26
 
23
27
  expect(create_space_command.template_name).to eq nil
24
28
 
@@ -31,7 +35,7 @@ describe Contentful::Bootstrap::Commands::CreateSpace do
31
35
  end
32
36
 
33
37
  it 'does not create json template when json_template is nil' do
34
- create_space_command = described_class.new(token, 'foo', 'bar', nil, false)
38
+ create_space_command = described_class.new(token, 'foo', 'bar', nil, false, false)
35
39
 
36
40
  expect(create_space_command.json_template).to eq nil
37
41
 
@@ -62,7 +66,7 @@ describe Contentful::Bootstrap::Commands::CreateSpace do
62
66
  allow_any_instance_of(described_class).to receive(:gets).and_return('y')
63
67
  allow_any_instance_of(Contentful::Bootstrap::Commands::GenerateToken).to receive(:gets).and_return('n')
64
68
 
65
- command = described_class.new(token, 'issue_22', nil, json_path)
69
+ command = described_class.new(token, 'issue_22', nil, json_path, false)
66
70
 
67
71
  vcr('issue_22') {
68
72
  command.run
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Contentful::Bootstrap::Commands::UpdateSpace do
4
+ let(:path) { File.expand_path(File.join('spec', 'fixtures', 'ini_fixtures', 'contentfulrc.ini')) }
5
+ let(:token) { Contentful::Bootstrap::Token.new path }
6
+ subject { Contentful::Bootstrap::Commands::UpdateSpace.new token, 'foo', 'bar', false, false }
7
+ let(:space_double) { SpaceDouble.new }
8
+
9
+ before do
10
+ allow(::File).to receive(:write)
11
+ end
12
+
13
+ describe 'instance methods' do
14
+ describe '#run' do
15
+ it 'with all non nil attributes' do
16
+ expect(subject).to receive(:fetch_space) { space_double }
17
+ expect(subject).to receive(:update_json_template).with(space_double)
18
+
19
+ expect(subject.run).to eq(space_double)
20
+ end
21
+
22
+ it 'exits if JSON not sent' do
23
+ update_space_command = described_class.new(token, 'foo', nil, false)
24
+
25
+ expect { update_space_command.run }.to raise_error SystemExit
26
+ end
27
+
28
+ it 'exits if space is not found' do
29
+ update_space_command = described_class.new(token, 'foo', 'bar', false)
30
+
31
+ expect(::Contentful::Management::Space).to receive(:find).with('foo').and_raise(::Contentful::Management::NotFound.new(ErrorRequestDouble.new))
32
+
33
+ expect { update_space_command.run }.to raise_error SystemExit
34
+ end
35
+
36
+ it 'exits if JSON template is not an existing file' do
37
+ expect(subject).to receive(:fetch_space) { space_double }
38
+
39
+ expect { subject.run }.to raise_error SystemExit
40
+ end
41
+
42
+ describe 'runs JSON Template without already processed elements' do
43
+ [true, false].each do |mark_processed|
44
+ it (mark_processed ? 'marks as processed after run' : 'doesnt modify input file after done') do
45
+ subject = described_class.new token, 'foo', 'bar', mark_processed, false
46
+
47
+ allow(::File).to receive(:exist?) { true }
48
+
49
+ mock_template = Object.new
50
+
51
+ expect(subject).to receive(:fetch_space) { space_double }
52
+ expect(mock_template).to receive(:run)
53
+
54
+ expect(::Contentful::Bootstrap::Templates::JsonTemplate).to receive(:new).with(space_double, 'bar', mark_processed, false) { mock_template }
55
+
56
+ subject.run
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ describe 'attributes' do
64
+ it ':json_template' do
65
+ expect(subject.json_template).to eq 'bar'
66
+ end
67
+ end
68
+ end
@@ -17,12 +17,20 @@ describe Contentful::Bootstrap::Templates::Base do
17
17
  expect(subject.assets).to eq []
18
18
  end
19
19
 
20
- it '#run' do
21
- ['content_types', 'assets', 'entries'].each do |name|
22
- expect(subject).to receive("create_#{name}".to_sym)
20
+ describe '#run' do
21
+ it 'calls create for each kind of object' do
22
+ ['content_types', 'assets', 'entries'].each do |name|
23
+ expect(subject).to receive("create_#{name}".to_sym)
24
+ end
25
+
26
+ subject.run
23
27
  end
24
28
 
25
- subject.run
29
+ it 'calls after_run when done' do
30
+ expect(subject).to receive(:after_run)
31
+
32
+ subject.run
33
+ end
26
34
  end
27
35
  end
28
36
 
@@ -2,9 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  describe Contentful::Bootstrap::Templates::JsonTemplate do
4
4
  let(:space) { Contentful::Management::Space.new }
5
- let(:path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'simple.json')) }
5
+ let(:path) { json_path('simple') }
6
6
  subject { described_class.new space, path }
7
7
 
8
+ before do
9
+ allow(::File).to receive(:write)
10
+ end
11
+
8
12
  describe 'instance methods' do
9
13
  describe '#content_types' do
10
14
  it 'fetches content types' do
@@ -63,10 +67,10 @@ describe Contentful::Bootstrap::Templates::JsonTemplate do
63
67
  end
64
68
 
65
69
  describe 'template version check' do
66
- let(:invalid_version_path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'invalid.json')) }
67
- let(:low_version_path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'low.json')) }
68
- let(:high_version_path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'high.json')) }
69
- let(:ok_version_path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'ok_version.json')) }
70
+ let(:invalid_version_path) { json_path('invalid') }
71
+ let(:low_version_path) { json_path('low') }
72
+ let(:high_version_path) { json_path('high') }
73
+ let(:ok_version_path) { json_path('ok_version') }
70
74
 
71
75
  it 'rejects templates without version' do
72
76
  expect { described_class.new space, invalid_version_path }.to raise_error "JSON Templates Version Mismatch. Current Version: 3"
@@ -86,7 +90,7 @@ describe Contentful::Bootstrap::Templates::JsonTemplate do
86
90
  end
87
91
 
88
92
  describe 'issues' do
89
- let(:link_entry_path) { File.expand_path(File.join('spec', 'fixtures', 'json_fixtures', 'links.json')) }
93
+ let(:link_entry_path) { json_path('links') }
90
94
 
91
95
  it 'links are not properly getting processed - #33' do
92
96
  subject = described_class.new space, link_entry_path
@@ -99,4 +103,69 @@ describe Contentful::Bootstrap::Templates::JsonTemplate do
99
103
  )
100
104
  end
101
105
  end
106
+
107
+ describe 'bootstrap processed' do
108
+ let(:processed_path) { json_path('processed') }
109
+
110
+ it 'filters content types that were already processed' do
111
+ json_fixture('processed') { |json|
112
+ expect(json['contentTypes'].size).to eq(2)
113
+ expect(json['contentTypes'].last['id']).to eq('dog')
114
+
115
+ subject = described_class.new(space, processed_path, false, false)
116
+
117
+ expect(subject.content_types.size).to eq(1)
118
+ expect(subject.content_types.first['id']).to eq('cat')
119
+ }
120
+ end
121
+
122
+ it 'filters assets that were already processed' do
123
+ json_fixture('processed') { |json|
124
+ expect(json['assets'].size).to eq(2)
125
+ expect(json['assets'].last['id']).to eq('dog_asset')
126
+
127
+ subject = described_class.new(space, processed_path, false, false)
128
+
129
+ expect(subject.assets.size).to eq(1)
130
+ expect(subject.assets.first['id']).to eq('cat_asset')
131
+ }
132
+ end
133
+
134
+ it 'filters entries that were already processed' do
135
+ json_fixture('processed') { |json|
136
+ expect(json['entries']['dog'].size).to eq(1)
137
+ expect(json['entries']['dog'].first['sys']['id']).to eq('doge')
138
+
139
+ subject = described_class.new(space, processed_path, false, false)
140
+
141
+ expect(subject.entries['dog'].size).to eq(0)
142
+ }
143
+ end
144
+ end
145
+
146
+ describe 'mark processed' do
147
+ it 'does not write file after run if not mark_processed' do
148
+ subject = described_class.new(space, path, false, false)
149
+ ['content_types', 'assets', 'entries'].each do |n|
150
+ allow(subject).to receive("create_#{n}".to_sym)
151
+ end
152
+
153
+ expect(subject).to receive(:after_run).and_call_original
154
+ expect(::File).not_to receive(:write)
155
+
156
+ subject.run
157
+ end
158
+
159
+ it 'writes file after run if mark_processed' do
160
+ subject = described_class.new(space, path, true, false)
161
+ ['content_types', 'assets', 'entries'].each do |n|
162
+ allow(subject).to receive("create_#{n}".to_sym)
163
+ end
164
+
165
+ expect(subject).to receive(:after_run).and_call_original
166
+ expect(::File).to receive(:write)
167
+
168
+ subject.run
169
+ end
170
+ end
102
171
  end
@@ -0,0 +1,72 @@
1
+ {
2
+ "version": 3,
3
+ "contentTypes": [
4
+ {
5
+ "id": "cat",
6
+ "name": "Cat",
7
+ "displayField": "name",
8
+ "fields": [
9
+ {
10
+ "id": "name",
11
+ "name": "Name",
12
+ "type": "Symbol"
13
+ }
14
+ ]
15
+ },
16
+ {
17
+ "id": "dog",
18
+ "bootstrapProcessed": true,
19
+ "name": "Dog",
20
+ "displayField": "name",
21
+ "fields": [
22
+ {
23
+ "id": "name",
24
+ "name": "Name",
25
+ "type": "Symbol"
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "assets": [
31
+ {
32
+ "id": "cat_asset",
33
+ "title": "Cat",
34
+ "file": {
35
+ "filename": "cat",
36
+ "url": "https://somecat.com/my_cat.jpeg"
37
+ }
38
+ },
39
+ {
40
+ "id": "dog_asset",
41
+ "bootstrapProcessed": true,
42
+ "title": "Dog",
43
+ "file": {
44
+ "filename": "Dog",
45
+ "url": "https://somedog.com/my_dog.jpeg"
46
+ }
47
+ }
48
+ ],
49
+ "entries": {
50
+ "cat": [
51
+ {
52
+ "sys": {
53
+ "id": "nyancat"
54
+ },
55
+ "fields": {
56
+ "name": "Nyan Cat"
57
+ }
58
+ }
59
+ ],
60
+ "dog": [
61
+ {
62
+ "sys": {
63
+ "id": "doge",
64
+ "bootstrapProcessed": true
65
+ },
66
+ "fields": {
67
+ "name": "Doge"
68
+ }
69
+ }
70
+ ]
71
+ }
72
+ }
data/spec/spec_helper.rb CHANGED
@@ -5,12 +5,16 @@ require 'vcr'
5
5
  require 'json'
6
6
 
7
7
  VCR.configure do |config|
8
- config.cassette_library_dir = "spec/fixtures/vcr_fixtures"
8
+ config.cassette_library_dir = File.join('spec', 'fixtures', 'vcr_fixtures')
9
9
  config.hook_into :webmock
10
10
  end
11
11
 
12
+ def json_path(name)
13
+ File.join('spec', 'fixtures', 'json_fixtures', "#{name}.json")
14
+ end
15
+
12
16
  def json_fixture(name)
13
- json = JSON.load(File.read("spec/fixtures/json_fixtures/#{name}.json"))
17
+ json = JSON.load(File.read(File.expand_path(json_path(name))))
14
18
  yield json if block_given?
15
19
  json
16
20
  end
@@ -42,6 +46,14 @@ class ServerDouble
42
46
  end
43
47
  end
44
48
 
49
+ class ErrorRequestDouble
50
+ def request; self; end
51
+ def endpoint; self; end
52
+ def error_message; self; end
53
+ def raw; self; end
54
+ def body; self; end
55
+ end
56
+
45
57
  class RequestDouble
46
58
  attr_accessor :query
47
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful_bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Litvak Bruno
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-02 00:00:00.000000000 Z
11
+ date: 2016-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -221,6 +221,7 @@ files:
221
221
  - lib/contentful/bootstrap/commands/create_space.rb
222
222
  - lib/contentful/bootstrap/commands/generate_json.rb
223
223
  - lib/contentful/bootstrap/commands/generate_token.rb
224
+ - lib/contentful/bootstrap/commands/update_space.rb
224
225
  - lib/contentful/bootstrap/constants.rb
225
226
  - lib/contentful/bootstrap/generator.rb
226
227
  - lib/contentful/bootstrap/management.rb
@@ -243,6 +244,7 @@ files:
243
244
  - spec/contentful/bootstrap/commands/create_space_spec.rb
244
245
  - spec/contentful/bootstrap/commands/generate_json_spec.rb
245
246
  - spec/contentful/bootstrap/commands/generate_token_spec.rb
247
+ - spec/contentful/bootstrap/commands/update_space_spec.rb
246
248
  - spec/contentful/bootstrap/generator_spec.rb
247
249
  - spec/contentful/bootstrap/management_spec.rb
248
250
  - spec/contentful/bootstrap/server_spec.rb
@@ -268,6 +270,7 @@ files:
268
270
  - spec/fixtures/json_fixtures/low.json
269
271
  - spec/fixtures/json_fixtures/no_ids.json
270
272
  - spec/fixtures/json_fixtures/ok_version.json
273
+ - spec/fixtures/json_fixtures/processed.json
271
274
  - spec/fixtures/json_fixtures/simple.json
272
275
  - spec/fixtures/json_fixtures/wl1z0pal05vy.json
273
276
  - spec/fixtures/vcr_fixtures/create_space.yml
@@ -309,6 +312,7 @@ test_files:
309
312
  - spec/contentful/bootstrap/commands/create_space_spec.rb
310
313
  - spec/contentful/bootstrap/commands/generate_json_spec.rb
311
314
  - spec/contentful/bootstrap/commands/generate_token_spec.rb
315
+ - spec/contentful/bootstrap/commands/update_space_spec.rb
312
316
  - spec/contentful/bootstrap/generator_spec.rb
313
317
  - spec/contentful/bootstrap/management_spec.rb
314
318
  - spec/contentful/bootstrap/server_spec.rb
@@ -334,6 +338,7 @@ test_files:
334
338
  - spec/fixtures/json_fixtures/low.json
335
339
  - spec/fixtures/json_fixtures/no_ids.json
336
340
  - spec/fixtures/json_fixtures/ok_version.json
341
+ - spec/fixtures/json_fixtures/processed.json
337
342
  - spec/fixtures/json_fixtures/simple.json
338
343
  - spec/fixtures/json_fixtures/wl1z0pal05vy.json
339
344
  - spec/fixtures/vcr_fixtures/create_space.yml