bookbindery 2.0.1 → 2.1.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/lib/bookbinder.rb +2 -2
- data/lib/bookbinder/app_fetcher.rb +2 -6
- data/lib/bookbinder/archive.rb +1 -1
- data/lib/bookbinder/book.rb +7 -2
- data/lib/bookbinder/cli.rb +4 -5
- data/lib/bookbinder/code_example_reader.rb +1 -1
- data/lib/bookbinder/command_validator.rb +30 -10
- data/lib/bookbinder/commands/bind.rb +58 -53
- data/lib/bookbinder/commands/help.rb +4 -4
- data/lib/bookbinder/commands/naming.rb +14 -4
- data/lib/bookbinder/commands/push_from_local.rb +51 -0
- data/lib/bookbinder/commands/push_to_prod.rb +1 -2
- data/lib/bookbinder/commands/run_publish_ci.rb +1 -1
- data/lib/bookbinder/commands/tag.rb +1 -1
- data/lib/bookbinder/commands/version.rb +5 -4
- data/lib/bookbinder/configuration.rb +49 -28
- data/lib/bookbinder/configuration_fetcher.rb +1 -1
- data/lib/bookbinder/configuration_validator.rb +40 -37
- data/lib/bookbinder/{bookbinder_logger.rb → deprecated_logger.rb} +1 -1
- data/lib/bookbinder/distributor.rb +16 -9
- data/lib/bookbinder/dita_html_to_middleman_formatter.rb +26 -8
- data/lib/bookbinder/dita_section.rb +8 -2
- data/lib/bookbinder/git_hub_repository.rb +7 -20
- data/lib/bookbinder/html_document_manipulator.rb +21 -0
- data/lib/bookbinder/ingest/cloner_factory.rb +25 -0
- data/lib/bookbinder/ingest/git_hub_repository_cloner_facade.rb +26 -0
- data/lib/bookbinder/ingest/local_filesystem_cloner_facade.rb +28 -0
- data/lib/bookbinder/local_dita_preprocessor.rb +33 -5
- data/lib/bookbinder/local_dita_to_html_converter.rb +26 -28
- data/lib/bookbinder/local_file_system_accessor.rb +0 -5
- data/lib/bookbinder/publisher.rb +1 -1
- data/lib/bookbinder/remote_yaml_credential_provider.rb +1 -1
- data/lib/bookbinder/repositories/command_repository.rb +21 -5
- data/lib/bookbinder/section.rb +12 -1
- data/lib/bookbinder/subnav.rb +4 -0
- data/lib/bookbinder/subnav_formatter.rb +37 -0
- data/lib/bookbinder/user_message.rb +10 -1
- data/master_middleman/bookbinder_helpers.rb +3 -3
- metadata +46 -40
- data/lib/bookbinder/commands/push_local_to_staging.rb +0 -36
@@ -38,10 +38,9 @@ module Bookbinder
|
|
38
38
|
build_number: arguments[0],
|
39
39
|
|
40
40
|
aws_credentials: config.aws_credentials,
|
41
|
-
cf_credentials: config.
|
41
|
+
cf_credentials: config.cf_credentials('production'),
|
42
42
|
|
43
43
|
book_repo: config.book_repo,
|
44
|
-
production: true
|
45
44
|
}
|
46
45
|
end
|
47
46
|
|
@@ -9,10 +9,6 @@ module Bookbinder
|
|
9
9
|
@logger = logger
|
10
10
|
end
|
11
11
|
|
12
|
-
def command_name
|
13
|
-
'--version'
|
14
|
-
end
|
15
|
-
|
16
12
|
def usage
|
17
13
|
[command_name, "Print the version of bookbinder"]
|
18
14
|
end
|
@@ -23,6 +19,11 @@ module Bookbinder
|
|
23
19
|
0
|
24
20
|
end
|
25
21
|
|
22
|
+
private
|
23
|
+
|
24
|
+
def command_name
|
25
|
+
'--version'
|
26
|
+
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require_relative 'remote_yaml_credential_provider'
|
2
|
-
require_relative 'git_hub_repository'
|
3
1
|
require 'git'
|
2
|
+
require_relative 'git_hub_repository'
|
3
|
+
require_relative 'remote_yaml_credential_provider'
|
4
4
|
|
5
5
|
module Bookbinder
|
6
6
|
class Configuration
|
@@ -8,14 +8,11 @@ module Bookbinder
|
|
8
8
|
CURRENT_SCHEMA_VERSION = '1.0.0'
|
9
9
|
STARTING_SCHEMA_VERSION = '1.0.0'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
class ConfigSchemaUnsupportedError < StandardError;
|
15
|
-
end
|
11
|
+
CredentialKeyError = Class.new(StandardError)
|
12
|
+
ConfigSchemaUnsupportedError = Class.new(StandardError)
|
16
13
|
|
17
14
|
class AwsCredentials
|
18
|
-
REQUIRED_KEYS = %w(access_key secret_key green_builds_bucket)
|
15
|
+
REQUIRED_KEYS = %w(access_key secret_key green_builds_bucket)
|
19
16
|
|
20
17
|
def initialize(cred_hash)
|
21
18
|
@creds = cred_hash
|
@@ -37,12 +34,11 @@ module Bookbinder
|
|
37
34
|
end
|
38
35
|
|
39
36
|
class CfCredentials
|
40
|
-
REQUIRED_KEYS = %w(api_endpoint organization app_name)
|
41
|
-
OPTIONAL_KEYS = %w(username password production_space production_host staging_space staging_host).freeze
|
37
|
+
REQUIRED_KEYS = %w(api_endpoint organization app_name)
|
42
38
|
|
43
|
-
def initialize(cred_hash,
|
39
|
+
def initialize(cred_hash, environment)
|
44
40
|
@creds = cred_hash
|
45
|
-
@
|
41
|
+
@environment = environment
|
46
42
|
end
|
47
43
|
|
48
44
|
REQUIRED_KEYS.each do |method_name|
|
@@ -51,15 +47,33 @@ module Bookbinder
|
|
51
47
|
end
|
52
48
|
end
|
53
49
|
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
def ==(other)
|
51
|
+
[@creds, @environment] == [
|
52
|
+
other.instance_variable_get(:@creds),
|
53
|
+
other.instance_variable_get(:@environment)
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def username
|
58
|
+
creds['username']
|
59
|
+
end
|
60
|
+
|
61
|
+
def password
|
62
|
+
creds['password']
|
63
|
+
end
|
64
|
+
|
65
|
+
def download_archive_before_push?
|
66
|
+
production?
|
67
|
+
end
|
68
|
+
|
69
|
+
def push_warning
|
70
|
+
if production?
|
71
|
+
'Warning: You are pushing to CF Docs production. Be careful.'
|
57
72
|
end
|
58
73
|
end
|
59
74
|
|
60
75
|
def routes
|
61
|
-
|
62
|
-
fetch(key) if correctly_formatted_domain_and_routes?(key)
|
76
|
+
fetch(host_key) if correctly_formatted_domain_and_routes?(host_key)
|
63
77
|
end
|
64
78
|
|
65
79
|
def flat_routes
|
@@ -70,13 +84,16 @@ module Bookbinder
|
|
70
84
|
end
|
71
85
|
|
72
86
|
def space
|
73
|
-
|
74
|
-
fetch(key)
|
87
|
+
fetch(space_key)
|
75
88
|
end
|
76
89
|
|
77
90
|
private
|
78
91
|
|
79
|
-
attr_reader :creds, :
|
92
|
+
attr_reader :creds, :environment
|
93
|
+
|
94
|
+
def production?
|
95
|
+
environment == 'production'
|
96
|
+
end
|
80
97
|
|
81
98
|
def fetch(key)
|
82
99
|
creds.fetch(key)
|
@@ -97,6 +114,14 @@ module Bookbinder
|
|
97
114
|
raise "Hosts in credentials must be nested as an array under the desired domain #{domain}." unless routes_hash[domain].is_a? Array
|
98
115
|
raise "Did you mean to provide a hostname for the domain #{domain}? Check your credentials.yml." if routes_hash[domain].any?(&:nil?)
|
99
116
|
end
|
117
|
+
|
118
|
+
def host_key
|
119
|
+
"#{environment}_host"
|
120
|
+
end
|
121
|
+
|
122
|
+
def space_key
|
123
|
+
"#{environment}_space"
|
124
|
+
end
|
100
125
|
end
|
101
126
|
|
102
127
|
attr_reader :schema_version, :schema_major_version, :schema_minor_version, :schema_patch_version
|
@@ -106,8 +131,8 @@ module Bookbinder
|
|
106
131
|
@config = config_hash
|
107
132
|
end
|
108
133
|
|
109
|
-
CONFIG_REQUIRED_KEYS = %w(book_repo public_host
|
110
|
-
CONFIG_OPTIONAL_KEYS = %w(archive_menu dita_sections layout_repo versions pdf_index cred_repo)
|
134
|
+
CONFIG_REQUIRED_KEYS = %w(book_repo public_host)
|
135
|
+
CONFIG_OPTIONAL_KEYS = %w(archive_menu dita_sections layout_repo versions pdf_index cred_repo pdf)
|
111
136
|
|
112
137
|
CONFIG_REQUIRED_KEYS.each do |method_name|
|
113
138
|
define_method(method_name) do
|
@@ -137,12 +162,8 @@ module Bookbinder
|
|
137
162
|
@aws_creds ||= AwsCredentials.new(credentials.fetch('aws'))
|
138
163
|
end
|
139
164
|
|
140
|
-
def
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
def cf_production_credentials
|
145
|
-
@cf_prod_creds ||= CfCredentials.new(credentials.fetch('cloud_foundry'), true)
|
165
|
+
def cf_credentials(environment)
|
166
|
+
CfCredentials.new(credentials.fetch('cloud_foundry'), environment)
|
146
167
|
end
|
147
168
|
|
148
169
|
def ==(o)
|
@@ -1,6 +1,40 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
2
|
|
3
3
|
module Bookbinder
|
4
|
+
class ConfigurationValidator
|
5
|
+
DuplicateSectionNameError = Class.new(RuntimeError)
|
6
|
+
MissingArchiveMenuPartialError = Class.new(RuntimeError)
|
7
|
+
EmptyArchiveItemsError = Class.new(RuntimeError)
|
8
|
+
ArchiveMenuNotDefinedError = Class.new(RuntimeError)
|
9
|
+
MissingRequiredKeyError = Class.new(RuntimeError)
|
10
|
+
|
11
|
+
def initialize(logger, file_system_accessor)
|
12
|
+
@logger = logger
|
13
|
+
@file_system_accessor = file_system_accessor
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?(config_hash, bookbinder_schema_version, starting_schema_version)
|
17
|
+
raise 'Your config.yml appears to be empty. Please check and try again.' unless config_hash
|
18
|
+
|
19
|
+
user_config_schema_version = config_hash['schema_version']
|
20
|
+
exceptions = [
|
21
|
+
RequiredKeysChecker.new,
|
22
|
+
ConfigVersionChecker.new(Version.parse(bookbinder_schema_version),
|
23
|
+
Version.parse(starting_schema_version),
|
24
|
+
VersionCheckerMessages.new(Version.parse(user_config_schema_version),
|
25
|
+
bookbinder_schema_version),
|
26
|
+
@logger),
|
27
|
+
DuplicateSectionNameChecker.new,
|
28
|
+
ArchiveMenuChecker.new(@file_system_accessor)
|
29
|
+
].map do |checker|
|
30
|
+
checker.check(config_hash)
|
31
|
+
end
|
32
|
+
exception = exceptions.compact.first
|
33
|
+
raise exception if exception
|
34
|
+
|
35
|
+
true
|
36
|
+
end
|
37
|
+
end
|
4
38
|
|
5
39
|
class DuplicateSectionNameChecker
|
6
40
|
def check(config)
|
@@ -12,8 +46,12 @@ module Bookbinder
|
|
12
46
|
private
|
13
47
|
|
14
48
|
def duplicate_section_names?(config)
|
15
|
-
|
16
|
-
|
49
|
+
if config['sections']
|
50
|
+
directory_names = config['sections'].map {|section| section['directory']}
|
51
|
+
directory_names.length != directory_names.uniq.length
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
17
55
|
end
|
18
56
|
|
19
57
|
end
|
@@ -147,39 +185,4 @@ module Bookbinder
|
|
147
185
|
end
|
148
186
|
end
|
149
187
|
end
|
150
|
-
|
151
|
-
class ConfigurationValidator
|
152
|
-
DuplicateSectionNameError = Class.new(RuntimeError)
|
153
|
-
MissingArchiveMenuPartialError = Class.new(RuntimeError)
|
154
|
-
EmptyArchiveItemsError = Class.new(RuntimeError)
|
155
|
-
ArchiveMenuNotDefinedError = Class.new(RuntimeError)
|
156
|
-
MissingRequiredKeyError = Class.new(RuntimeError)
|
157
|
-
|
158
|
-
def initialize(logger, file_system_accessor)
|
159
|
-
@logger = logger
|
160
|
-
@file_system_accessor = file_system_accessor
|
161
|
-
end
|
162
|
-
|
163
|
-
def valid?(config_hash, bookbinder_schema_version, starting_schema_version)
|
164
|
-
raise 'Your config.yml appears to be empty. Please check and try again.' unless config_hash
|
165
|
-
|
166
|
-
user_config_schema_version = config_hash['schema_version']
|
167
|
-
exceptions = [
|
168
|
-
RequiredKeysChecker.new,
|
169
|
-
ConfigVersionChecker.new(Version.parse(bookbinder_schema_version),
|
170
|
-
Version.parse(starting_schema_version),
|
171
|
-
VersionCheckerMessages.new(Version.parse(user_config_schema_version),
|
172
|
-
bookbinder_schema_version),
|
173
|
-
@logger),
|
174
|
-
DuplicateSectionNameChecker.new,
|
175
|
-
ArchiveMenuChecker.new(@file_system_accessor)
|
176
|
-
].map do |checker|
|
177
|
-
checker.check(config_hash)
|
178
|
-
end
|
179
|
-
exception = exceptions.compact.first
|
180
|
-
raise exception if exception
|
181
|
-
|
182
|
-
true
|
183
|
-
end
|
184
|
-
end
|
185
188
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'app_fetcher'
|
2
|
+
require_relative 'artifact_namer'
|
2
3
|
|
3
4
|
module Bookbinder
|
4
5
|
class Distributor
|
@@ -27,14 +28,18 @@ module Bookbinder
|
|
27
28
|
|
28
29
|
def distribute
|
29
30
|
begin
|
30
|
-
download if
|
31
|
+
download if cf_credentials.download_archive_before_push?
|
31
32
|
push_app
|
32
33
|
nil
|
33
34
|
rescue => e
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
@logger.error(<<-ERROR.chomp)
|
36
|
+
[ERROR] #{e.message}
|
37
|
+
[DEBUG INFO]
|
38
|
+
CF organization: #{cf_credentials.organization}
|
39
|
+
CF space: #{cf_credentials.space}
|
40
|
+
CF account: #{cf_credentials.username}
|
41
|
+
routes: #{cf_credentials.routes}
|
42
|
+
ERROR
|
38
43
|
ensure
|
39
44
|
upload_trace
|
40
45
|
end
|
@@ -45,12 +50,14 @@ module Bookbinder
|
|
45
50
|
attr_reader :options, :archive, :namer, :namespace, :pusher
|
46
51
|
|
47
52
|
def download
|
48
|
-
archive.download(download_dir: options[:app_dir],
|
53
|
+
archive.download(download_dir: options[:app_dir],
|
54
|
+
bucket: options[:aws_credentials].green_builds_bucket,
|
55
|
+
build_number: options[:build_number],
|
49
56
|
namespace: namespace)
|
50
57
|
end
|
51
58
|
|
52
59
|
def push_app
|
53
|
-
warn if
|
60
|
+
@logger.warn(cf_credentials.push_warning) if cf_credentials.push_warning
|
54
61
|
pusher.push(options[:app_dir])
|
55
62
|
end
|
56
63
|
|
@@ -62,8 +69,8 @@ module Bookbinder
|
|
62
69
|
@logger.error "Could not find CF trace file: #{namer.full_path}"
|
63
70
|
end
|
64
71
|
|
65
|
-
def
|
66
|
-
|
72
|
+
def cf_credentials
|
73
|
+
options[:cf_credentials]
|
67
74
|
end
|
68
75
|
end
|
69
76
|
end
|
@@ -1,19 +1,24 @@
|
|
1
|
+
require_relative 'subnav'
|
2
|
+
|
1
3
|
module Bookbinder
|
2
4
|
|
3
5
|
class DitaHtmlToMiddlemanFormatter
|
4
|
-
def initialize(file_system_accessor)
|
6
|
+
def initialize(file_system_accessor, subnav_formatter, html_document_manipulator)
|
5
7
|
@file_system_accessor = file_system_accessor
|
8
|
+
@subnav_formatter = subnav_formatter
|
9
|
+
@html_document_manipulator = html_document_manipulator
|
6
10
|
end
|
7
11
|
|
8
|
-
def
|
12
|
+
def format_html(src, dest)
|
9
13
|
all_files_with_ext = file_system_accessor.find_files_with_ext('.html', src)
|
10
14
|
|
11
15
|
all_files_with_ext.map do |filepath|
|
12
|
-
|
13
|
-
|
16
|
+
file_text = file_system_accessor.read filepath
|
17
|
+
file_title_text = html_document_manipulator.read_html_in_tag(document: file_text,
|
18
|
+
tag: 'title')
|
14
19
|
|
15
|
-
file_body_text =
|
16
|
-
|
20
|
+
file_body_text = html_document_manipulator.read_html_in_tag(document: file_text,
|
21
|
+
tag: 'body')
|
17
22
|
|
18
23
|
relative_path_to_file = file_system_accessor.relative_path_from(src, filepath)
|
19
24
|
new_filepath = File.join dest, "#{relative_path_to_file}.erb"
|
@@ -24,14 +29,27 @@ module Bookbinder
|
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
32
|
+
def format_subnav(dita_section,
|
33
|
+
subnav_template_text,
|
34
|
+
json_props_location,
|
35
|
+
unformatted_subnav_text)
|
36
|
+
formatted_json_links = subnav_formatter.get_links_as_json(unformatted_subnav_text, dita_section.directory)
|
37
|
+
|
38
|
+
nav_text = html_document_manipulator.set_attribute(document: subnav_template_text,
|
39
|
+
selector: 'div.nav-content',
|
40
|
+
attribute: 'data-props-location',
|
41
|
+
value: json_props_location)
|
42
|
+
Subnav.new(formatted_json_links, nav_text)
|
43
|
+
end
|
44
|
+
|
27
45
|
private
|
28
46
|
|
29
|
-
attr_reader :file_system_accessor
|
47
|
+
attr_reader :file_system_accessor, :subnav_formatter, :html_document_manipulator
|
30
48
|
|
31
49
|
def frontmatter(title)
|
32
50
|
sanitized_title = title.gsub('"', '\"')
|
33
51
|
"---\ntitle: \"#{sanitized_title}\"\ndita: true\n---\n"
|
34
52
|
end
|
35
|
-
|
36
53
|
end
|
54
|
+
|
37
55
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'bookbinder/shell_out'
|
2
1
|
require 'git'
|
3
|
-
require_relative '
|
2
|
+
require_relative 'deprecated_logger'
|
4
3
|
require_relative 'git_client'
|
4
|
+
require_relative 'shell_out'
|
5
5
|
|
6
6
|
module Bookbinder
|
7
7
|
class GitHubRepository
|
@@ -13,14 +13,11 @@ module Bookbinder
|
|
13
13
|
|
14
14
|
def self.build_from_remote(logger,
|
15
15
|
section_hash,
|
16
|
-
target_ref,
|
17
16
|
git_accessor)
|
18
17
|
full_name = section_hash.fetch('repository', {}).fetch('name')
|
19
|
-
target_ref = target_ref || section_hash.fetch('repository', {})['ref']
|
20
18
|
directory = section_hash['directory']
|
21
19
|
new(logger: logger,
|
22
20
|
full_name: full_name,
|
23
|
-
target_ref: target_ref,
|
24
21
|
github_token: ENV['GITHUB_API_TOKEN'],
|
25
22
|
directory: directory,
|
26
23
|
git_accessor: git_accessor)
|
@@ -42,7 +39,6 @@ module Bookbinder
|
|
42
39
|
|
43
40
|
def initialize(logger: nil,
|
44
41
|
full_name: nil,
|
45
|
-
target_ref: nil,
|
46
42
|
github_token: nil,
|
47
43
|
directory: nil,
|
48
44
|
local_repo_dir: nil,
|
@@ -50,7 +46,6 @@ module Bookbinder
|
|
50
46
|
@logger = logger
|
51
47
|
raise 'No full_name provided ' unless full_name
|
52
48
|
@full_name = full_name
|
53
|
-
@target_ref = target_ref
|
54
49
|
@directory = directory
|
55
50
|
@local_repo_dir = local_repo_dir
|
56
51
|
|
@@ -75,7 +70,7 @@ module Bookbinder
|
|
75
70
|
@directory || short_name
|
76
71
|
end
|
77
72
|
|
78
|
-
def copy_from_remote(destination_dir)
|
73
|
+
def copy_from_remote(destination_dir, target_ref)
|
79
74
|
begin
|
80
75
|
@git_base_object = git_accessor.clone("git@github.com:#{full_name}",
|
81
76
|
directory,
|
@@ -131,22 +126,14 @@ module Bookbinder
|
|
131
126
|
@logger.log ' skipping (not found) '.magenta + path_to_local_repo
|
132
127
|
end
|
133
128
|
|
134
|
-
def path_to_local_repo
|
135
|
-
if @local_repo_dir
|
136
|
-
File.join(@local_repo_dir, short_name)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def has_git_object?
|
141
|
-
!!@git_base_object
|
142
|
-
end
|
143
|
-
|
144
129
|
private
|
145
130
|
|
146
131
|
attr_reader :git_accessor
|
147
132
|
|
148
|
-
def
|
149
|
-
@
|
133
|
+
def path_to_local_repo
|
134
|
+
if @local_repo_dir
|
135
|
+
File.join(@local_repo_dir, short_name)
|
136
|
+
end
|
150
137
|
end
|
151
138
|
|
152
139
|
def tags
|