contentful_bootstrap 3.4.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|