bookbindery 2.0.1 → 2.1.0

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