contentful_bootstrap 3.4.0 → 3.5.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -1
- data/README.md +19 -8
- data/bin/contentful_bootstrap +13 -1
- data/contentful_bootstrap.gemspec +2 -2
- data/lib/contentful/bootstrap/command_runner.rb +3 -15
- data/lib/contentful/bootstrap/commands/base.rb +27 -13
- data/lib/contentful/bootstrap/commands/create_space.rb +41 -39
- data/lib/contentful/bootstrap/commands/generate_json.rb +3 -2
- data/lib/contentful/bootstrap/commands/generate_token.rb +20 -19
- data/lib/contentful/bootstrap/commands/update_space.rb +15 -14
- data/lib/contentful/bootstrap/support.rb +18 -1
- data/lib/contentful/bootstrap/templates/base.rb +16 -11
- data/lib/contentful/bootstrap/templates/json_template.rb +14 -6
- data/lib/contentful/bootstrap/version.rb +1 -1
- data/spec/contentful/bootstrap/command_runner_spec.rb +6 -6
- data/spec/contentful/bootstrap/commands/base_spec.rb +35 -21
- data/spec/contentful/bootstrap/commands/create_space_spec.rb +16 -16
- data/spec/contentful/bootstrap/commands/generate_token_spec.rb +19 -22
- data/spec/contentful/bootstrap/commands/update_space_spec.rb +6 -6
- data/spec/contentful/bootstrap/support_spec.rb +1 -3
- data/spec/contentful/bootstrap/templates/base_spec.rb +2 -2
- data/spec/contentful/bootstrap/templates/json_template_spec.rb +19 -4
- data/spec/fixtures/json_fixtures/object.json +38 -0
- data/spec/spec_helper.rb +20 -0
- metadata +17 -9
@@ -9,42 +9,43 @@ module Contentful
|
|
9
9
|
module Commands
|
10
10
|
class GenerateToken < Base
|
11
11
|
attr_reader :token_name
|
12
|
-
def initialize(token, space,
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def initialize(token, space, options = {})
|
13
|
+
@token_name = options.fetch(:token_name, 'Bootstrap Token')
|
14
|
+
|
15
|
+
super(token, space, options)
|
16
16
|
end
|
17
17
|
|
18
18
|
def run
|
19
|
-
|
19
|
+
output 'Creating Delivery API Token'
|
20
20
|
|
21
21
|
fetch_space
|
22
22
|
|
23
23
|
access_token = fetch_access_token
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
output "Token '#{token_name}' created! - '#{access_token}'"
|
26
|
+
Support.input('Do you want to write the Delivery Token to your configuration file? (Y/n): ', no_input) do |answer|
|
27
|
+
unless answer.downcase == 'n'
|
28
|
+
@token.write_access_token(@actual_space.name, access_token)
|
29
|
+
@token.write_space_id(@actual_space.name, @actual_space.id)
|
30
|
+
end
|
30
31
|
end
|
31
32
|
|
32
33
|
access_token
|
33
34
|
end
|
34
35
|
|
35
36
|
def fetch_space
|
36
|
-
@
|
37
|
+
if @space.is_a?(String)
|
38
|
+
@actual_space = client.spaces.find(@space)
|
39
|
+
else
|
40
|
+
@actual_space = @space
|
41
|
+
end
|
37
42
|
end
|
38
43
|
|
39
44
|
def fetch_access_token
|
40
|
-
|
41
|
-
|
42
|
-
'
|
43
|
-
|
44
|
-
).post
|
45
|
-
fail response if response.object.is_a?(Contentful::Management::Error)
|
46
|
-
|
47
|
-
response.object['accessToken']
|
45
|
+
@actual_space.api_keys.create(
|
46
|
+
name: token_name,
|
47
|
+
description: "Created with 'contentful_bootstrap.rb v#{Contentful::Bootstrap::VERSION}'"
|
48
|
+
).access_token
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
@@ -8,27 +8,28 @@ module Contentful
|
|
8
8
|
module Commands
|
9
9
|
class UpdateSpace < Base
|
10
10
|
attr_reader :json_template
|
11
|
-
def initialize(token, space_id,
|
12
|
-
|
13
|
-
@
|
14
|
-
@
|
15
|
-
|
11
|
+
def initialize(token, space_id, options = {})
|
12
|
+
@json_template = options.fetch(:json_template, nil)
|
13
|
+
@mark_processed = options.fetch(:mark_processed, false)
|
14
|
+
@skip_content_types = options.fetch(:skip_content_types, false)
|
15
|
+
|
16
|
+
super(token, space_id, options)
|
16
17
|
end
|
17
18
|
|
18
19
|
def run
|
19
20
|
if @json_template.nil?
|
20
|
-
|
21
|
+
output 'JSON Template not found. Exiting!'
|
21
22
|
exit(1)
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
output "Updating Space '#{@space}'"
|
25
26
|
|
26
27
|
update_space = fetch_space
|
27
28
|
|
28
29
|
update_json_template(update_space)
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
output
|
32
|
+
output "Successfully updated Space #{@space}"
|
32
33
|
|
33
34
|
update_space
|
34
35
|
end
|
@@ -36,9 +37,9 @@ module Contentful
|
|
36
37
|
protected
|
37
38
|
|
38
39
|
def fetch_space
|
39
|
-
|
40
|
+
client.spaces.find(@space)
|
40
41
|
rescue Contentful::Management::NotFound
|
41
|
-
|
42
|
+
output 'Space Not Found. Exiting!'
|
42
43
|
exit(1)
|
43
44
|
end
|
44
45
|
|
@@ -46,11 +47,11 @@ module Contentful
|
|
46
47
|
|
47
48
|
def update_json_template(space)
|
48
49
|
if ::File.exist?(@json_template)
|
49
|
-
|
50
|
+
output "Updating from JSON Template '#{@json_template}'"
|
50
51
|
Templates::JsonTemplate.new(space, @json_template, @mark_processed, false, @skip_content_types).run
|
51
|
-
|
52
|
+
output "JSON Template '#{@json_template}' updated!"
|
52
53
|
else
|
53
|
-
|
54
|
+
output "JSON Template '#{@json_template}' does not exist. Please check that you specified the correct file name."
|
54
55
|
exit(1)
|
55
56
|
end
|
56
57
|
end
|
@@ -3,13 +3,30 @@ require 'stringio'
|
|
3
3
|
module Contentful
|
4
4
|
module Bootstrap
|
5
5
|
module Support
|
6
|
-
def silence_stderr
|
6
|
+
def self.silence_stderr
|
7
7
|
old_stderr = $stderr
|
8
8
|
$stderr = StringIO.new
|
9
9
|
yield
|
10
10
|
ensure
|
11
11
|
$stderr = old_stderr
|
12
12
|
end
|
13
|
+
|
14
|
+
def self.output(text = nil, quiet = false)
|
15
|
+
if text.nil?
|
16
|
+
puts unless quiet
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
puts text unless quiet
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.input(prompt_text, no_input = false)
|
24
|
+
return if no_input
|
25
|
+
|
26
|
+
print prompt_text
|
27
|
+
answer = gets.chomp
|
28
|
+
yield answer if block_given?
|
29
|
+
end
|
13
30
|
end
|
14
31
|
end
|
15
32
|
end
|
@@ -8,8 +8,9 @@ module Contentful
|
|
8
8
|
class Base
|
9
9
|
attr_reader :space, :skip_content_types
|
10
10
|
|
11
|
-
def initialize(space, skip_content_types = false)
|
11
|
+
def initialize(space, quiet = false, skip_content_types = false)
|
12
12
|
@space = space
|
13
|
+
@quiet = quiet
|
13
14
|
@skip_content_types = skip_content_types
|
14
15
|
end
|
15
16
|
|
@@ -21,9 +22,9 @@ module Contentful
|
|
21
22
|
after_run
|
22
23
|
rescue Contentful::Management::Error => e
|
23
24
|
error = e.error
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
output "Error at: #{error[:url]}"
|
26
|
+
output "Message: #{error[:message]}"
|
27
|
+
output "Details: #{error[:details]}"
|
27
28
|
|
28
29
|
raise e
|
29
30
|
end
|
@@ -45,6 +46,10 @@ module Contentful
|
|
45
46
|
|
46
47
|
protected
|
47
48
|
|
49
|
+
def output(text = nil)
|
50
|
+
Support.output(text, @quiet)
|
51
|
+
end
|
52
|
+
|
48
53
|
def create_file(name, url, properties = {})
|
49
54
|
image = Contentful::Management::File.new
|
50
55
|
image.properties[:contentType] = properties.fetch(:contentType, 'image/jpeg')
|
@@ -58,7 +63,7 @@ module Contentful
|
|
58
63
|
def create_content_types
|
59
64
|
content_types.each do |ct|
|
60
65
|
begin
|
61
|
-
|
66
|
+
output "Creating Content Type '#{ct['name']}'"
|
62
67
|
|
63
68
|
fields = []
|
64
69
|
content_type = space.content_types.new
|
@@ -88,7 +93,7 @@ module Contentful
|
|
88
93
|
content_type.save
|
89
94
|
content_type.activate
|
90
95
|
rescue Contentful::Management::Conflict
|
91
|
-
|
96
|
+
output "ContentType '#{ct['id']}' already created! Skipping"
|
92
97
|
next
|
93
98
|
end
|
94
99
|
end
|
@@ -105,7 +110,7 @@ module Contentful
|
|
105
110
|
def create_assets
|
106
111
|
assets.each do |asset|
|
107
112
|
begin
|
108
|
-
|
113
|
+
output "Creating Asset '#{asset['title']}'"
|
109
114
|
asset = space.assets.create(
|
110
115
|
id: asset['id'],
|
111
116
|
title: asset['title'],
|
@@ -124,7 +129,7 @@ module Contentful
|
|
124
129
|
attempts += 1
|
125
130
|
end
|
126
131
|
rescue Contentful::Management::Conflict
|
127
|
-
|
132
|
+
output "Asset '#{asset['id']}' already created! Skipping"
|
128
133
|
next
|
129
134
|
end
|
130
135
|
end
|
@@ -168,14 +173,14 @@ module Contentful
|
|
168
173
|
end
|
169
174
|
|
170
175
|
begin
|
171
|
-
|
176
|
+
output "Creating Entry #{e[:id]}"
|
172
177
|
entry = content_type.entries.create({:id => e[:id]})
|
173
178
|
entry.save
|
174
179
|
|
175
180
|
e = e.clone
|
176
181
|
e[:id] = entry.id # in case no ID was specified in template
|
177
182
|
rescue Contentful::Management::Conflict
|
178
|
-
|
183
|
+
output "Entry '#{e[:id]}' already exists! Skipping"
|
179
184
|
ensure
|
180
185
|
next e
|
181
186
|
end
|
@@ -183,7 +188,7 @@ module Contentful
|
|
183
188
|
end.flatten
|
184
189
|
|
185
190
|
processed_entries = processed_entries.map do |e|
|
186
|
-
|
191
|
+
output "Populating Entry #{e[:id]}"
|
187
192
|
|
188
193
|
entry = space.entries.find(e[:id])
|
189
194
|
e.delete(:id)
|
@@ -16,8 +16,8 @@ module Contentful
|
|
16
16
|
|
17
17
|
attr_reader :assets, :entries, :content_types
|
18
18
|
|
19
|
-
def initialize(space, file, mark_processed = false, all = true, skip_content_types = false)
|
20
|
-
super(space, skip_content_types)
|
19
|
+
def initialize(space, file, mark_processed = false, all = true, quiet = false, skip_content_types = false)
|
20
|
+
super(space, quiet, skip_content_types)
|
21
21
|
@file = file
|
22
22
|
@all = all
|
23
23
|
@mark_processed = mark_processed
|
@@ -68,7 +68,7 @@ module Contentful
|
|
68
68
|
def json
|
69
69
|
@json ||= ::JSON.parse(::File.read(@file))
|
70
70
|
rescue
|
71
|
-
|
71
|
+
output 'File is not JSON. Exiting!'
|
72
72
|
exit(1)
|
73
73
|
end
|
74
74
|
|
@@ -127,8 +127,8 @@ module Contentful
|
|
127
127
|
processed_entry['id'] = entry[SYS_KEY]['id'] if entry.key?(SYS_KEY) && entry[SYS_KEY].key?('id')
|
128
128
|
|
129
129
|
entry.fetch('fields', {}).each do |field, value|
|
130
|
-
link_fields << field if value
|
131
|
-
array_fields << field if value
|
130
|
+
link_fields << field if is_link?(value)
|
131
|
+
array_fields << field if is_array?(value)
|
132
132
|
|
133
133
|
unless link_fields.include?(field) || array_fields.include?(field)
|
134
134
|
processed_entry[field] = value
|
@@ -141,7 +141,7 @@ module Contentful
|
|
141
141
|
|
142
142
|
array_fields.each do |af|
|
143
143
|
processed_entry[af] = entry['fields'][af].map do |item|
|
144
|
-
|
144
|
+
is_link?(item) ? create_link(item) : item
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -172,6 +172,14 @@ module Contentful
|
|
172
172
|
def mark_processed?
|
173
173
|
@mark_processed
|
174
174
|
end
|
175
|
+
|
176
|
+
def is_link?(value)
|
177
|
+
value.is_a?(::Hash) && value.key?('id') && value.key?('linkType')
|
178
|
+
end
|
179
|
+
|
180
|
+
def is_array?(value)
|
181
|
+
value.is_a?(::Array)
|
182
|
+
end
|
175
183
|
end
|
176
184
|
end
|
177
185
|
end
|
@@ -12,7 +12,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
12
12
|
|
13
13
|
it 'default values' do
|
14
14
|
expect(Contentful::Bootstrap::Commands::CreateSpace).to receive(:new).with(
|
15
|
-
subject.token, 'foo',
|
15
|
+
subject.token, 'foo', {}
|
16
16
|
).and_call_original
|
17
17
|
|
18
18
|
subject.create_space('foo')
|
@@ -20,7 +20,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
20
20
|
|
21
21
|
it 'with options' do
|
22
22
|
expect(Contentful::Bootstrap::Commands::CreateSpace).to receive(:new).with(
|
23
|
-
subject.token, 'foo', 'bar', 'baz', true, false
|
23
|
+
subject.token, 'foo', template: 'bar', json_template: 'baz', mark_processed: true, trigger_oauth: false
|
24
24
|
).and_call_original
|
25
25
|
|
26
26
|
subject.create_space('foo', template: 'bar', json_template: 'baz', mark_processed: true, trigger_oauth: false)
|
@@ -40,7 +40,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
40
40
|
|
41
41
|
it 'default values' do
|
42
42
|
expect(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:new).with(
|
43
|
-
subject.token, 'foo',
|
43
|
+
subject.token, 'foo', {}
|
44
44
|
).and_call_original
|
45
45
|
|
46
46
|
subject.update_space('foo')
|
@@ -48,7 +48,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
48
48
|
|
49
49
|
it 'with options' do
|
50
50
|
expect(Contentful::Bootstrap::Commands::UpdateSpace).to receive(:new).with(
|
51
|
-
subject.token, 'foo', 'bar', true, false
|
51
|
+
subject.token, 'foo', json_template: 'bar', mark_processed: true, trigger_oauth: false
|
52
52
|
).and_call_original
|
53
53
|
|
54
54
|
subject.update_space('foo', json_template: 'bar', mark_processed: true, trigger_oauth: false)
|
@@ -69,7 +69,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
69
69
|
|
70
70
|
it 'default values' do
|
71
71
|
expect(Contentful::Bootstrap::Commands::GenerateToken).to receive(:new).with(
|
72
|
-
subject.token, 'foo',
|
72
|
+
subject.token, 'foo', {}
|
73
73
|
).and_call_original
|
74
74
|
|
75
75
|
subject.generate_token('foo')
|
@@ -77,7 +77,7 @@ describe Contentful::Bootstrap::CommandRunner do
|
|
77
77
|
|
78
78
|
it 'with options' do
|
79
79
|
expect(Contentful::Bootstrap::Commands::GenerateToken).to receive(:new).with(
|
80
|
-
subject.token, 'foo', 'bar', false
|
80
|
+
subject.token, 'foo', name: 'bar', trigger_oauth: false
|
81
81
|
).and_call_original
|
82
82
|
|
83
83
|
subject.generate_token('foo', name: 'bar', trigger_oauth: false)
|
@@ -7,7 +7,7 @@ describe Contentful::Bootstrap::Commands::Base do
|
|
7
7
|
let(:no_token_path) { File.expand_path(File.join('spec', 'fixtures', 'ini_fixtures', 'no_token.ini')) }
|
8
8
|
let(:token) { Contentful::Bootstrap::Token.new path }
|
9
9
|
let(:non_management_token) { Contentful::Bootstrap::Token.new no_token_path }
|
10
|
-
subject {
|
10
|
+
subject { described_class.new(token, 'foo', trigger_oauth: false, quiet: true) }
|
11
11
|
|
12
12
|
describe 'abstract methods' do
|
13
13
|
it '#run' do
|
@@ -18,35 +18,35 @@ describe Contentful::Bootstrap::Commands::Base do
|
|
18
18
|
describe 'initialize' do
|
19
19
|
describe 'configuration' do
|
20
20
|
it 'runs configuration when trigger_oauth is true' do
|
21
|
-
expect_any_instance_of(
|
22
|
-
|
21
|
+
expect_any_instance_of(described_class).to receive(:configuration)
|
22
|
+
described_class.new(token, 'foo', quiet: true)
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'doesnt run configuration when trigger_oauth is false' do
|
26
|
-
expect_any_instance_of(
|
27
|
-
|
26
|
+
expect_any_instance_of(described_class).not_to receive(:configuration)
|
27
|
+
described_class.new(token, 'foo', trigger_oauth: false, quiet: true)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
describe 'management_client_init' do
|
32
32
|
it 'runs management_client_init when trigger_oauth is true' do
|
33
|
-
expect_any_instance_of(
|
34
|
-
|
33
|
+
expect_any_instance_of(described_class).to receive(:management_client_init)
|
34
|
+
described_class.new(token, 'foo', quiet: true)
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'doesnt run management_client_init when trigger_oauth is false' do
|
38
|
-
expect_any_instance_of(
|
39
|
-
|
38
|
+
expect_any_instance_of(described_class).not_to receive(:management_client_init)
|
39
|
+
described_class.new(token, 'foo', trigger_oauth: false, quiet: true)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
describe 'instance methods' do
|
45
45
|
it '#management_client_init' do
|
46
|
-
allow_any_instance_of(
|
46
|
+
allow_any_instance_of(described_class).to receive(:configuration)
|
47
47
|
expect(Contentful::Management::Client).to receive(:new).with(token.read, raise_errors: true)
|
48
48
|
|
49
|
-
|
49
|
+
described_class.new(token, 'foo', quiet: true)
|
50
50
|
end
|
51
51
|
|
52
52
|
describe '#configuration' do
|
@@ -55,35 +55,35 @@ describe Contentful::Bootstrap::Commands::Base do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'passes if token is found' do
|
58
|
-
expect {
|
58
|
+
expect { described_class.new(token, 'foo') }.to output("OAuth token found, moving on!\n").to_stdout
|
59
59
|
end
|
60
60
|
|
61
61
|
describe 'token not found' do
|
62
62
|
it 'exits if answer is no' do
|
63
|
-
|
64
|
-
expect {
|
63
|
+
expect(Contentful::Bootstrap::Support).to receive(:gets) { "n" }
|
64
|
+
expect { described_class.new(non_management_token, 'foo', quiet: true) }.to raise_error SystemExit
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'runs token_server if other answer' do
|
68
|
-
|
69
|
-
expect_any_instance_of(
|
68
|
+
expect(Contentful::Bootstrap::Support).to receive(:gets) { "y" }
|
69
|
+
expect_any_instance_of(described_class).to receive(:token_server)
|
70
70
|
|
71
|
-
|
71
|
+
described_class.new(non_management_token, 'foo', quiet: true)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
it '#token_server' do
|
77
|
-
allow_any_instance_of(
|
77
|
+
allow_any_instance_of(described_class).to receive(:management_client_init)
|
78
78
|
|
79
|
-
|
79
|
+
expect(Contentful::Bootstrap::Support).to receive(:gets) { "y" }
|
80
80
|
expect_any_instance_of(Contentful::Bootstrap::Server).to receive(:start) {}
|
81
81
|
expect_any_instance_of(Contentful::Bootstrap::Server).to receive(:running?) { true }
|
82
82
|
expect(Net::HTTP).to receive(:get).with(URI('http://localhost:5123')) {}
|
83
83
|
expect(non_management_token).to receive(:present?).and_return(false, true)
|
84
84
|
expect_any_instance_of(Contentful::Bootstrap::Server).to receive(:stop) {}
|
85
85
|
|
86
|
-
|
86
|
+
described_class.new(non_management_token, 'foo', quiet: true)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -97,6 +97,20 @@ describe Contentful::Bootstrap::Commands::Base do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
describe '
|
100
|
+
describe 'additional options' do
|
101
|
+
describe ':no_input' do
|
102
|
+
it ':no_input will disallow all input operations' do
|
103
|
+
expect_any_instance_of(described_class).not_to receive(:token_server)
|
104
|
+
expect(Contentful::Bootstrap::Support).not_to receive(:gets)
|
105
|
+
expect { described_class.new(non_management_token, 'foo', quiet: true, no_input: true) }.to raise_error "OAuth token required to proceed"
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'without :no_input input operations are allowed' do
|
109
|
+
expect_any_instance_of(described_class).to receive(:token_server)
|
110
|
+
expect(Contentful::Bootstrap::Support).to receive(:gets) { "y" }
|
111
|
+
allow(non_management_token).to receive(:read) { true }
|
112
|
+
described_class.new(non_management_token, 'foo', quiet: true, no_input: false)
|
113
|
+
end
|
114
|
+
end
|
101
115
|
end
|
102
116
|
end
|