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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bookbinder.rb +2 -2
  3. data/lib/bookbinder/app_fetcher.rb +2 -6
  4. data/lib/bookbinder/archive.rb +1 -1
  5. data/lib/bookbinder/book.rb +7 -2
  6. data/lib/bookbinder/cli.rb +4 -5
  7. data/lib/bookbinder/code_example_reader.rb +1 -1
  8. data/lib/bookbinder/command_validator.rb +30 -10
  9. data/lib/bookbinder/commands/bind.rb +58 -53
  10. data/lib/bookbinder/commands/help.rb +4 -4
  11. data/lib/bookbinder/commands/naming.rb +14 -4
  12. data/lib/bookbinder/commands/push_from_local.rb +51 -0
  13. data/lib/bookbinder/commands/push_to_prod.rb +1 -2
  14. data/lib/bookbinder/commands/run_publish_ci.rb +1 -1
  15. data/lib/bookbinder/commands/tag.rb +1 -1
  16. data/lib/bookbinder/commands/version.rb +5 -4
  17. data/lib/bookbinder/configuration.rb +49 -28
  18. data/lib/bookbinder/configuration_fetcher.rb +1 -1
  19. data/lib/bookbinder/configuration_validator.rb +40 -37
  20. data/lib/bookbinder/{bookbinder_logger.rb → deprecated_logger.rb} +1 -1
  21. data/lib/bookbinder/distributor.rb +16 -9
  22. data/lib/bookbinder/dita_html_to_middleman_formatter.rb +26 -8
  23. data/lib/bookbinder/dita_section.rb +8 -2
  24. data/lib/bookbinder/git_hub_repository.rb +7 -20
  25. data/lib/bookbinder/html_document_manipulator.rb +21 -0
  26. data/lib/bookbinder/ingest/cloner_factory.rb +25 -0
  27. data/lib/bookbinder/ingest/git_hub_repository_cloner_facade.rb +26 -0
  28. data/lib/bookbinder/ingest/local_filesystem_cloner_facade.rb +28 -0
  29. data/lib/bookbinder/local_dita_preprocessor.rb +33 -5
  30. data/lib/bookbinder/local_dita_to_html_converter.rb +26 -28
  31. data/lib/bookbinder/local_file_system_accessor.rb +0 -5
  32. data/lib/bookbinder/publisher.rb +1 -1
  33. data/lib/bookbinder/remote_yaml_credential_provider.rb +1 -1
  34. data/lib/bookbinder/repositories/command_repository.rb +21 -5
  35. data/lib/bookbinder/section.rb +12 -1
  36. data/lib/bookbinder/subnav.rb +4 -0
  37. data/lib/bookbinder/subnav_formatter.rb +37 -0
  38. data/lib/bookbinder/user_message.rb +10 -1
  39. data/master_middleman/bookbinder_helpers.rb +3 -3
  40. metadata +46 -40
  41. data/lib/bookbinder/commands/push_local_to_staging.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8da72c5e68bd509530fa1ce2bbff37521223d5c
4
- data.tar.gz: 1339eff7f48eeaea5bdfdd2e91f9cefc6c813533
3
+ metadata.gz: abe74d9727cc4ccb6456bb2c8e6b5474a99951b7
4
+ data.tar.gz: 80e90cd7e5c6f7582eb2c41683c75e0b7df2f10c
5
5
  SHA512:
6
- metadata.gz: a6d61852a9dc656b5aeddfc23b87ea57147ac4b3ff3faac4d7b01afd02242891d7f2aae37fb82c869441c5a3979dbbbda50891c37e1fb13d9dbf82727fdd196f
7
- data.tar.gz: dd24ebb1819201b38eb6213ffe80ec7c8e50d675d89b98c12a60ba4459681847a5d2b58833a1f5fe3e3b4fce87351434550e3d45511ef3160a4699ca3d36a0b2
6
+ metadata.gz: 5e16a8861042949b496d942efa08fb59441ca789f7f73bfaa244a1b5b1c9cf266b267d3333b389e4f1f88c565bb9c622fbb3879b7f7c5ce5348247f04d0d0c8b
7
+ data.tar.gz: 6a12e088c5ec3ca21f2f229b92235eec8644fc18cc4c86e71eb5a7beb9e60a8f97dca26e9ee72072e2082f32007b3c34bcfaa300556e252d9923bd68ff847b74
data/lib/bookbinder.rb CHANGED
@@ -11,7 +11,7 @@ require 'vienna'
11
11
  require 'popen4'
12
12
  require 'puma'
13
13
 
14
- require_relative 'bookbinder/bookbinder_logger'
14
+ require_relative 'bookbinder/deprecated_logger'
15
15
  require_relative 'bookbinder/git_client'
16
16
  require_relative 'bookbinder/section'
17
17
  require_relative 'bookbinder/book'
@@ -39,7 +39,7 @@ require_relative 'bookbinder/distributor'
39
39
  require_relative 'bookbinder/commands/bookbinder_command'
40
40
  require_relative 'bookbinder/commands/build_and_push_tarball'
41
41
  require_relative 'bookbinder/commands/bind'
42
- require_relative 'bookbinder/commands/push_local_to_staging'
42
+ require_relative 'bookbinder/commands/push_from_local'
43
43
  require_relative 'bookbinder/commands/push_to_prod'
44
44
  require_relative 'bookbinder/commands/run_publish_ci'
45
45
  require_relative 'bookbinder/commands/update_local_doc_repos'
@@ -17,12 +17,8 @@ module Bookbinder
17
17
  cf_routes.apps_by_host_and_domain.has_key?([host, domain])
18
18
  end
19
19
 
20
- app_groups =
21
- if existing_hosts.any?
22
- existing_hosts.map { |domain, host| apps_for_host(cf_routes, domain, host) }
23
- else
24
- raise "cannot find currently deployed app."
25
- end
20
+ return nil if existing_hosts.empty?
21
+ app_groups = existing_hosts.map { |domain, host| apps_for_host(cf_routes, domain, host) }
26
22
  apps_for_existing_routes = app_groups.first
27
23
  apps_for_existing_routes.first
28
24
  end
@@ -1,7 +1,7 @@
1
1
  require 'fog/aws'
2
2
  require 'tmpdir'
3
- require_relative 'bookbinder_logger'
4
3
  require_relative 'artifact_namer'
4
+ require_relative 'deprecated_logger'
5
5
 
6
6
  module Bookbinder
7
7
  class Archive
@@ -23,9 +23,10 @@ module Bookbinder
23
23
  git_accessor: git_accessor)
24
24
  end
25
25
 
26
+ @target_ref = target_ref || 'master'
27
+
26
28
  @repository = GitHubRepository.new(logger: logger,
27
29
  full_name: full_name,
28
- target_ref: target_ref,
29
30
  github_token: github_token,
30
31
  git_accessor: git_accessor)
31
32
  @git_accessor = git_accessor
@@ -44,11 +45,15 @@ module Bookbinder
44
45
  end
45
46
 
46
47
  def copy_from_remote(destination_dir)
47
- @repository.copy_from_remote(destination_dir)
48
+ @repository.copy_from_remote(destination_dir, target_ref)
48
49
  end
49
50
 
50
51
  def tag_self_and_sections_with(tag)
51
52
  (@section_vcs_repos + [@repository]).each { |repo| repo.tag_with tag }
52
53
  end
54
+
55
+ private
56
+
57
+ attr_reader :target_ref
53
58
  end
54
59
  end
@@ -9,10 +9,9 @@ require_relative 'user_message_presenter'
9
9
  module Bookbinder
10
10
  class Cli
11
11
  def run(args)
12
- command_name = args[0]
13
- command_arguments = args[1..-1]
12
+ command_name, *command_arguments = args
14
13
 
15
- logger = BookbinderLogger.new
14
+ logger = DeprecatedLogger.new
16
15
  commands = Repositories::CommandRepository.new(logger)
17
16
 
18
17
  command_validator = CommandValidator.new(commands, commands.help.usage_message)
@@ -24,11 +23,11 @@ module Bookbinder
24
23
  terminal = Terminal.new
25
24
 
26
25
  user_message = command_validator.validate(command_name)
27
- if user_message.escalation_type == EscalationType.error
26
+ if user_message.error?
28
27
  error_message = user_message_presenter.get_error(user_message)
29
28
  terminal.update(error_message)
30
29
  return 1
31
- elsif user_message.escalation_type == EscalationType.warn
30
+ elsif user_message.warn?
32
31
  warning_message = user_message_presenter.get_warning(user_message)
33
32
  terminal.update(warning_message)
34
33
  end
@@ -1,4 +1,4 @@
1
- require_relative '../../lib/bookbinder/bookbinder_logger'
1
+ require_relative '../../lib/bookbinder/deprecated_logger'
2
2
 
3
3
  module Bookbinder
4
4
  class CodeExampleReader
@@ -1,5 +1,6 @@
1
- require_relative 'cli_error'
2
1
  require 'ostruct'
2
+ require_relative 'cli_error'
3
+ require_relative 'commands/naming'
3
4
  require_relative 'user_message'
4
5
 
5
6
  module Bookbinder
@@ -9,20 +10,39 @@ module Bookbinder
9
10
  @usage_text = usage_text
10
11
  end
11
12
 
12
- def validate command_name
13
- command_type = "#{command_name}".match(/^--/) ? 'flag' : 'command'
14
- if commands.none? { |command| command.command_for?(command_name) }
15
- UserMessage.new "Unrecognized #{command_type} '#{command_name}'\n" + usage_text, EscalationType.error
16
- elsif command = commands.find { |command| (command.respond_to? :deprecated_command_for?) &&
17
- (command.deprecated_command_for? command_name) }
18
- UserMessage.new "Use of #{command_name} is deprecated. " +
19
- "The preferred usage is below: \n#{command.usage}",
20
- EscalationType.warn
13
+ def validate(command_name)
14
+ candidate = Candidate.new(command_name, commands)
15
+ if candidate.unrecognized?
16
+ UserMessage.new(
17
+ "Unrecognized #{candidate.command_type} '#{command_name}'\n#{usage_text}",
18
+ EscalationType.error
19
+ )
20
+ elsif candidate.deprecated_match
21
+ UserMessage.new(
22
+ "Use of #{command_name} is deprecated. " +
23
+ "The preferred usage is below: \n#{candidate.deprecated_match.usage}",
24
+ EscalationType.warn
25
+ )
21
26
  else
22
27
  UserMessage.new "Success", EscalationType.success
23
28
  end
24
29
  end
25
30
 
31
+ Candidate = Struct.new(:command_name, :commands) do
32
+ include Bookbinder::Commands::Naming
33
+
34
+ def unrecognized?
35
+ commands.none? { |command| command.command_for?(command_name) }
36
+ end
37
+
38
+ def deprecated_match
39
+ @deprecated_match ||= commands.find { |command|
40
+ command.respond_to?(:deprecated_command_for?) &&
41
+ command.deprecated_command_for?(command_name)
42
+ }
43
+ end
44
+ end
45
+
26
46
  private
27
47
 
28
48
  attr_reader :commands, :usage_text
@@ -26,7 +26,8 @@ module Bookbinder
26
26
  final_app_directory,
27
27
  server_director,
28
28
  context_dir,
29
- dita_preprocessor)
29
+ dita_preprocessor,
30
+ cloner_factory)
30
31
  @logger = logger
31
32
  @config_fetcher = config_fetcher
32
33
  @archive_menu_config = archive_menu_config
@@ -38,6 +39,7 @@ module Bookbinder
38
39
  @server_director = server_director
39
40
  @context_dir = context_dir
40
41
  @dita_preprocessor = dita_preprocessor
42
+ @cloner_factory = cloner_factory
41
43
  end
42
44
 
43
45
  def usage
@@ -60,23 +62,27 @@ module Bookbinder
60
62
 
61
63
  @publisher = Publisher.new(logger, sitemap_generator, static_site_generator, server_director, file_system_accessor)
62
64
 
63
- location = cli_arguments[0]
65
+ bind_source, *options = cli_arguments
64
66
 
65
- output_paths = output_directory_paths(location)
66
- publish_config = publish_config(location)
67
- @versions = publish_config.fetch(:versions, [])
68
- @book_repo = publish_config[:book_repo]
67
+ output_paths = output_directory_paths(bind_source)
68
+
69
+ bind_config = bind_config(bind_source)
70
+ @versions = bind_config.fetch(:versions, [])
71
+ @book_repo = bind_config[:book_repo]
69
72
 
70
73
  master_middleman_dir = output_paths.fetch(:master_middleman_dir)
71
74
  output_dir = output_paths.fetch(:output_dir)
72
75
 
76
+ master_dir = File.join output_dir, 'master_middleman'
77
+ workspace_dir = File.join master_dir, 'source'
78
+
73
79
  dita_processing_dir = File.join output_dir, 'dita'
74
80
  dita_section_dir = File.join dita_processing_dir, 'dita_sections'
75
81
  dita_processed_dir = File.join dita_processing_dir, 'html_from_dita'
82
+ subnavs_dir = File.join workspace_dir, 'subnavs'
83
+ dita_subnav_template_path = File.join workspace_dir, 'subnavs', '_dita_subnav_template.erb'
76
84
  formatted_dir = File.join dita_processing_dir, 'site_generator_ready'
77
85
 
78
- master_dir = File.join output_dir, 'master_middleman'
79
- workspace_dir = File.join master_dir, 'source'
80
86
  prepare_directories(final_app_directory,
81
87
  output_dir,
82
88
  workspace_dir,
@@ -95,11 +101,11 @@ module Bookbinder
95
101
  DitaSection.new(nil, relative_path_to_dita_map, full_name, target_ref, directory)
96
102
  end
97
103
 
98
- if location == 'github'
104
+ if bind_source == 'github'
99
105
  dita_section_gatherer = DitaSectionGatherer.new(version_control_system, logger)
100
- final_dita_sections = dita_section_gatherer.gather(dita_sections, to: dita_section_dir)
106
+ gathered_dita_sections = dita_section_gatherer.gather(dita_sections, to: dita_section_dir)
101
107
  else
102
- final_dita_sections = dita_sections.map do |dita_section|
108
+ gathered_dita_sections = dita_sections.map do |dita_section|
103
109
  relative_path_to_dita_map = dita_section.ditamap_location
104
110
  full_name = dita_section.full_name
105
111
  target_ref = dita_section.target_ref
@@ -111,17 +117,32 @@ module Bookbinder
111
117
  end
112
118
  end
113
119
 
114
- dita_preprocessor.preprocess final_dita_sections, dita_processed_dir, formatted_dir, workspace_dir
120
+ gathered_dita_sections.each do |dita_section|
121
+ dita_preprocessor.preprocess(dita_section,
122
+ dita_processed_dir,
123
+ formatted_dir,
124
+ workspace_dir,
125
+ subnavs_dir,
126
+ dita_subnav_template_path)
127
+ end
115
128
 
116
- sections = gather_sections(workspace_dir, output_paths)
129
+ cloner = cloner_factory.produce(
130
+ bind_source,
131
+ output_paths[:local_repo_dir]
132
+ )
133
+ sections = gather_sections(
134
+ workspace_dir,
135
+ cloner,
136
+ ('master' if options.include?('--ignore-section-refs'))
137
+ )
117
138
 
118
- subnavs = subnavs_by_dir_name(sections)
139
+ subnavs = (sections + gathered_dita_sections).map(&:subnav).reduce(&:merge)
119
140
 
120
141
  success = publisher.publish(
121
142
  subnavs,
122
143
  {verbose: cli_arguments.include?('--verbose')},
123
144
  output_paths,
124
- archive_menu_config.generate(publish_config, sections)
145
+ archive_menu_config.generate(bind_config, sections)
125
146
  )
126
147
 
127
148
  success ? 0 : 1
@@ -140,23 +161,20 @@ module Bookbinder
140
161
  :sitemap_generator,
141
162
  :server_director,
142
163
  :context_dir,
143
- :dita_preprocessor
164
+ :dita_preprocessor,
165
+ :cloner_factory
144
166
 
145
- def gather_sections(workspace, output_paths)
167
+ def gather_sections(workspace, cloner, ref_override)
146
168
  config.sections.map do |attributes|
147
-
148
- local_repo_dir = output_paths[:local_repo_dir]
149
- vcs_repo =
150
- if local_repo_dir
151
- GitHubRepository.
152
- build_from_local(logger, attributes, local_repo_dir, version_control_system).
153
- tap { |repo| repo.copy_from_local(workspace) }
154
- else
155
- GitHubRepository.
156
- build_from_remote(logger, attributes, nil, version_control_system).
157
- tap { |repo| repo.copy_from_remote(workspace) }
158
- end
159
-
169
+ target_ref = ref_override ||
170
+ attributes.fetch('repository', {})['ref'] ||
171
+ 'master'
172
+ repo_name = attributes.fetch('repository').fetch('name')
173
+ directory = attributes['directory']
174
+ vcs_repo = cloner.call(from: repo_name,
175
+ ref: target_ref,
176
+ parent_dir: workspace,
177
+ dir_name: directory)
160
178
  @section_repository.get_instance(attributes,
161
179
  vcs_repo: vcs_repo,
162
180
  destination_dir: workspace,
@@ -217,8 +235,8 @@ module Bookbinder
217
235
  end
218
236
  end
219
237
 
220
- def output_directory_paths(location)
221
- local_repo_dir = (location == 'local') ? File.expand_path('..', context_dir) : nil
238
+ def output_directory_paths(bind_source)
239
+ local_repo_dir = (bind_source == 'local') ? File.expand_path('..', context_dir) : nil
222
240
 
223
241
  {
224
242
  final_app_dir: final_app_directory,
@@ -228,7 +246,7 @@ module Bookbinder
228
246
  }
229
247
  end
230
248
 
231
- def publish_config(location)
249
+ def bind_config(bind_source)
232
250
  arguments = {
233
251
  sections: config.sections,
234
252
  book_repo: config.book_repo,
@@ -238,7 +256,7 @@ module Bookbinder
238
256
 
239
257
  optional_arguments = {}
240
258
  optional_arguments.merge!(template_variables: config.template_variables) if config.respond_to?(:template_variables)
241
- if publishing_to_github? location
259
+ if binding_from_github? bind_source
242
260
  config.versions.each { |version| arguments[:sections].concat sections_from version }
243
261
  optional_arguments.merge!(versions: config.versions)
244
262
  end
@@ -281,9 +299,8 @@ module Bookbinder
281
299
  destination_dir = Dir.mktmpdir
282
300
  repository = GitHubRepository.build_from_remote(logger,
283
301
  section,
284
- 'master',
285
302
  version_control_system)
286
- repository.copy_from_remote(destination_dir)
303
+ repository.copy_from_remote(destination_dir, 'master')
287
304
  if repository
288
305
  File.join(destination_dir, repository.directory)
289
306
  else
@@ -296,25 +313,13 @@ module Bookbinder
296
313
  end
297
314
 
298
315
  def arguments_are_valid?(arguments)
299
- return false unless arguments.any?
300
- verbose = arguments[1] && arguments[1..-1].include?('--verbose')
301
- tag_provided = arguments[1] && (arguments[1..-1] - ['--verbose']).any?
302
- nothing_special = arguments[1..-1].empty?
303
-
304
- %w(local github).include?(arguments[0]) && (tag_provided || verbose || nothing_special)
316
+ bind_source, *options = arguments
317
+ valid_options = %w(--verbose --ignore-section-refs).to_set
318
+ %w(local github).include?(bind_source) && options.to_set.subset?(valid_options)
305
319
  end
306
320
 
307
- def publishing_to_github?(publish_location)
308
- config.has_option?('versions') && publish_location != 'local'
309
- end
310
-
311
- def subnavs_by_dir_name(sections)
312
- sections.reduce({}) do |subnavs, section|
313
- namespace = section.directory.gsub('/', '_')
314
- template = section.subnav_template || 'default'
315
-
316
- subnavs.merge(namespace => template)
317
- end
321
+ def binding_from_github?(bind_location)
322
+ config.has_option?('versions') && bind_location != 'local'
318
323
  end
319
324
  end
320
325
  end
@@ -10,10 +10,6 @@ module Bookbinder
10
10
  @other_commands = other_commands
11
11
  end
12
12
 
13
- def command_name
14
- '--help'
15
- end
16
-
17
13
  def usage
18
14
  [command_name, "Print this message"]
19
15
  end
@@ -29,6 +25,10 @@ module Bookbinder
29
25
 
30
26
  private
31
27
 
28
+ def command_name
29
+ '--help'
30
+ end
31
+
32
32
  def command_usage_messages
33
33
  (flags + standard_commands).reduce('') { |message, command|
34
34
  "#{message}#{usage_indent}#{formatted_usage(command)}\n"
@@ -3,10 +3,6 @@ require 'active_support/inflector'
3
3
  module Bookbinder
4
4
  module Commands
5
5
  module Naming
6
- def command_name
7
- self.class.name.demodulize.underscore
8
- end
9
-
10
6
  def command_for?(test_command_name)
11
7
  command_name == test_command_name
12
8
  end
@@ -14,6 +10,20 @@ module Bookbinder
14
10
  def flag?
15
11
  command_name.match(/^--/)
16
12
  end
13
+
14
+ def command_type
15
+ if flag?
16
+ 'flag'
17
+ else
18
+ 'command'
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def command_name
25
+ self.class.name.demodulize.underscore
26
+ end
17
27
  end
18
28
  end
19
29
  end
@@ -0,0 +1,51 @@
1
+ require_relative '../distributor'
2
+ require_relative 'bookbinder_command'
3
+ require_relative 'naming'
4
+
5
+ module Bookbinder
6
+ module Commands
7
+ class PushFromLocal
8
+ include Commands::Naming
9
+
10
+ def initialize(logger, configuration_fetcher, environment)
11
+ @logger = logger
12
+ @configuration_fetcher = configuration_fetcher
13
+ @environment = environment
14
+ end
15
+
16
+ def usage
17
+ [command_name,
18
+ "Push the contents of final_app to the #{environment} host specified in credentials.yml"]
19
+ end
20
+
21
+ def run(_)
22
+ Distributor.build(@logger, options).distribute
23
+ 0
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :configuration_fetcher, :environment
29
+
30
+ def config
31
+ @config ||= configuration_fetcher.fetch_config
32
+ end
33
+
34
+ def command_name
35
+ "push_local_to_#{environment}"
36
+ end
37
+
38
+ def options
39
+ {
40
+ app_dir: './final_app',
41
+ build_number: ENV['BUILD_NUMBER'],
42
+
43
+ aws_credentials: config.aws_credentials,
44
+ cf_credentials: config.cf_credentials(environment),
45
+
46
+ book_repo: config.book_repo,
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end