bookbindery 2.1.5 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bookbinder.rb +0 -4
  3. data/lib/bookbinder/cf_command_runner.rb +11 -5
  4. data/lib/bookbinder/cli.rb +8 -12
  5. data/lib/bookbinder/colorizer.rb +1 -2
  6. data/lib/bookbinder/command_runner.rb +0 -2
  7. data/lib/bookbinder/commands/bind.rb +96 -99
  8. data/lib/bookbinder/commands/bind/directory_preparer.rb +60 -0
  9. data/lib/bookbinder/commands/build_and_push_tarball.rb +5 -4
  10. data/lib/bookbinder/commands/push_from_local.rb +56 -2
  11. data/lib/bookbinder/commands/push_to_prod.rb +6 -2
  12. data/lib/bookbinder/commands/tag.rb +15 -3
  13. data/lib/bookbinder/config/aws_credentials.rb +21 -0
  14. data/lib/bookbinder/config/cf_credentials.rb +87 -0
  15. data/lib/bookbinder/configuration.rb +4 -140
  16. data/lib/bookbinder/configuration_fetcher.rb +28 -4
  17. data/lib/bookbinder/configuration_validator.rb +11 -164
  18. data/lib/bookbinder/distributor.rb +16 -12
  19. data/lib/bookbinder/{dita_to_html_converter.rb → dita_command_creator.rb} +5 -17
  20. data/lib/bookbinder/dita_preprocessor.rb +14 -12
  21. data/lib/bookbinder/git_accessor.rb +21 -2
  22. data/lib/bookbinder/git_hub_repository.rb +0 -43
  23. data/lib/bookbinder/ingest/cloner_factory.rb +5 -4
  24. data/lib/bookbinder/ingest/destination_directory.rb +15 -0
  25. data/lib/bookbinder/ingest/git_hub_repository_cloner.rb +22 -13
  26. data/lib/bookbinder/ingest/local_filesystem_cloner.rb +38 -14
  27. data/lib/bookbinder/ingest/working_copy.rb +31 -0
  28. data/lib/bookbinder/local_dita_section_gatherer.rb +4 -3
  29. data/lib/bookbinder/local_file_system_accessor.rb +1 -4
  30. data/lib/bookbinder/middleman_runner.rb +22 -26
  31. data/lib/bookbinder/remote_yaml_credential_provider.rb +10 -10
  32. data/lib/bookbinder/repositories/command_repository.rb +18 -12
  33. data/lib/bookbinder/repositories/section_repository.rb +8 -8
  34. data/lib/bookbinder/server_director.rb +16 -33
  35. data/lib/bookbinder/sheller.rb +33 -7
  36. data/lib/bookbinder/spider.rb +3 -0
  37. data/lib/bookbinder/streams/switchable_stdout_and_red_stderr.rb +38 -0
  38. data/lib/bookbinder/terminal.rb +11 -1
  39. data/lib/bookbinder/validation_checkers/archive_menu_checker.rb +31 -0
  40. data/lib/bookbinder/validation_checkers/config_version_checker.rb +91 -0
  41. data/lib/bookbinder/validation_checkers/dita_section_checker.rb +20 -0
  42. data/lib/bookbinder/validation_checkers/duplicate_section_name_checker.rb +25 -0
  43. data/lib/bookbinder/validation_checkers/repository_name_presence_checker.rb +33 -0
  44. data/lib/bookbinder/validation_checkers/required_keys_checker.rb +43 -0
  45. data/lib/bookbinder/values/dita_section.rb +5 -1
  46. data/lib/bookbinder/values/output_locations.rb +25 -2
  47. data/lib/bookbinder/values/user_message.rb +2 -2
  48. data/master_middleman/bookbinder_helpers.rb +5 -15
  49. data/template_app/Gemfile.lock +1 -1
  50. metadata +60 -80
  51. data/lib/bookbinder/commands/generate_pdf.rb +0 -141
  52. data/lib/bookbinder/pdf_generator.rb +0 -73
  53. data/lib/bookbinder/publisher.rb +0 -58
  54. data/lib/bookbinder/user_message_presenter.rb +0 -21
@@ -1,6 +1,7 @@
1
- require_relative 'naming'
2
- require_relative 'bookbinder_command'
3
1
  require_relative '../archive'
2
+ require_relative '../ingest/destination_directory'
3
+ require_relative 'bookbinder_command'
4
+ require_relative 'naming'
4
5
 
5
6
  module Bookbinder
6
7
  module Commands
@@ -21,10 +22,10 @@ module Bookbinder
21
22
  def run(_)
22
23
  raise MissingBuildNumber unless ENV['BUILD_NUMBER']
23
24
  config = configuration_fetcher.fetch_config
24
- aws_credentials = config.aws_credentials
25
+ aws_credentials = configuration_fetcher.fetch_credentials[:aws]
25
26
  archive = Archive.new(logger: @logger, key: aws_credentials.access_key, secret: aws_credentials.secret_key)
26
27
  archive.create_and_upload_tarball(build_number: ENV['BUILD_NUMBER'], bucket: aws_credentials.green_builds_bucket,
27
- namespace: GitHubRepository.new(logger: @logger, full_name: config.book_repo, git_accessor: Git).short_name)
28
+ namespace: Ingest::DestinationDirectory.new(config.book_repo, nil))
28
29
  0
29
30
  end
30
31
  end
@@ -7,6 +7,10 @@ module Bookbinder
7
7
  class PushFromLocal
8
8
  include Commands::Naming
9
9
 
10
+ CredentialKeyError = Class.new(RuntimeError)
11
+ REQUIRED_AWS_KEYS = %w(access_key secret_key green_builds_bucket)
12
+ REQUIRED_CF_KEYS = %w(username password api_endpoint organization app_name)
13
+
10
14
  def initialize(logger, configuration_fetcher, environment)
11
15
  @logger = logger
12
16
  @configuration_fetcher = configuration_fetcher
@@ -19,6 +23,7 @@ module Bookbinder
19
23
  end
20
24
 
21
25
  def run(_)
26
+ validate
22
27
  Distributor.build(@logger, options).distribute
23
28
  0
24
29
  end
@@ -36,16 +41,65 @@ module Bookbinder
36
41
  end
37
42
 
38
43
  def options
44
+ credentials = configuration_fetcher.fetch_credentials(environment)
39
45
  {
40
46
  app_dir: './final_app',
41
47
  build_number: ENV['BUILD_NUMBER'],
42
48
 
43
- aws_credentials: config.aws_credentials,
44
- cf_credentials: config.cf_credentials(environment),
49
+ aws_credentials: credentials[:aws],
50
+ cf_credentials: credentials[:cloud_foundry],
45
51
 
46
52
  book_repo: config.book_repo,
47
53
  }
48
54
  end
55
+
56
+ def error_message
57
+ <<-ERROR
58
+ Cannot locate a specific key in credentials.yml.
59
+ Your credentials file should follow this format:
60
+
61
+ aws:
62
+ access_key: <your_AWS_access_key>
63
+ secret_key: <your_AWS_secret_key>
64
+ green_builds_bucket: <your_AWS_bucket>
65
+
66
+ cloud_foundry:
67
+ username: <your_CF_account>
68
+ password: <your_CF_password>
69
+ staging_space: <your_CF_staging_space_name>
70
+ staging_host: <your_CF_staging_host_name>
71
+ <your-domain.com>:
72
+ - <your_hostname>
73
+ production_space: <your_CF_production_space_name>
74
+ production_host: <your_CF_production_host_name>
75
+ <your-domain.com>:
76
+ - <your_hostname>
77
+ app_name: <your_app_name>
78
+ api_endpoint: <your_api_endpoint>
79
+ organization: <your_organization>
80
+ ERROR
81
+ end
82
+
83
+ def validate
84
+ missing_keys = []
85
+
86
+ creds = configuration_fetcher.fetch_credentials(environment)
87
+ aws_creds = creds[:aws]
88
+ cf_creds = creds[:cloud_foundry]
89
+
90
+ missing_keys << 'aws' unless aws_creds
91
+ missing_keys << 'cloud_foundry' unless cf_creds
92
+
93
+ REQUIRED_AWS_KEYS.map do |key|
94
+ missing_keys << key unless aws_creds.send(key)
95
+ end
96
+
97
+ REQUIRED_CF_KEYS.each do |key|
98
+ missing_keys << key unless cf_creds.send(key)
99
+ end
100
+
101
+ raise CredentialKeyError.new error_message if missing_keys.any?
102
+ end
49
103
  end
50
104
  end
51
105
  end
@@ -37,13 +37,17 @@ module Bookbinder
37
37
  app_dir: Dir.mktmpdir,
38
38
  build_number: arguments[0],
39
39
 
40
- aws_credentials: config.aws_credentials,
41
- cf_credentials: config.cf_credentials('production'),
40
+ aws_credentials: credentials[:aws],
41
+ cf_credentials: credentials[:cloud_foundry],
42
42
 
43
43
  book_repo: config.book_repo,
44
44
  }
45
45
  end
46
46
 
47
+ def credentials
48
+ configuration_fetcher.fetch_credentials('production')
49
+ end
50
+
47
51
  def config
48
52
  @config ||= configuration_fetcher.fetch_config
49
53
  end
@@ -1,14 +1,18 @@
1
1
  require_relative '../book'
2
- require_relative '../errors/cli_error'
3
2
  require_relative '../deprecated_logger'
4
- require_relative 'bookbinder_command'
3
+ require_relative '../errors/cli_error'
5
4
  require_relative 'naming'
6
5
 
7
6
  module Bookbinder
8
7
  module Commands
9
- class Tag < BookbinderCommand
8
+ class Tag
10
9
  include Commands::Naming
11
10
 
11
+ def initialize(logger, configuration_fetcher)
12
+ @logger = logger
13
+ @configuration_fetcher = configuration_fetcher
14
+ end
15
+
12
16
  def usage
13
17
  ["tag <git tag>", "Apply the specified <git tag> to your book and all sections of your book"]
14
18
  end
@@ -25,6 +29,14 @@ module Bookbinder
25
29
  @logger.log " #{book.full_name.yellow} and its sections were tagged with #{tag.blue}"
26
30
  0
27
31
  end
32
+
33
+ private
34
+
35
+ attr_reader :configuration_fetcher
36
+
37
+ def config
38
+ @config ||= configuration_fetcher.fetch_config
39
+ end
28
40
  end
29
41
  end
30
42
  end
@@ -0,0 +1,21 @@
1
+ module Bookbinder
2
+ module Config
3
+ class AwsCredentials
4
+ REQUIRED_KEYS = %w(access_key secret_key green_builds_bucket)
5
+
6
+ def initialize(aws_cred_hash)
7
+ @creds = aws_cred_hash
8
+ end
9
+
10
+ REQUIRED_KEYS.each do |method_name|
11
+ define_method(method_name) do
12
+ creds[method_name]
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :creds
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,87 @@
1
+ module Bookbinder
2
+ module Config
3
+ class CfCredentials
4
+ REQUIRED_KEYS = %w(username password api_endpoint organization app_name)
5
+ CredentialKeyError = Class.new(RuntimeError)
6
+
7
+ def initialize(cf_cred_hash, environment)
8
+ @creds = cf_cred_hash
9
+ @environment = environment
10
+ end
11
+
12
+ REQUIRED_KEYS.each do |method_name|
13
+ define_method(method_name) do
14
+ creds[method_name]
15
+ end
16
+ end
17
+
18
+ def ==(other)
19
+ [@creds, @environment] == [
20
+ other.instance_variable_get(:@creds),
21
+ other.instance_variable_get(:@environment)
22
+ ]
23
+ end
24
+
25
+ def download_archive_before_push?
26
+ production?
27
+ end
28
+
29
+ def push_warning
30
+ if production?
31
+ 'Warning: You are pushing to CF Docs production. Be careful.'
32
+ end
33
+ end
34
+
35
+ def routes
36
+ fetch(host_key) if correctly_formatted_domain_and_routes?(host_key)
37
+ end
38
+
39
+ def flat_routes
40
+ routes.reduce([]) do |all_routes, domain_apps|
41
+ domain, apps = domain_apps
42
+ all_routes + apps.map { |app| [domain, app] }
43
+ end
44
+ end
45
+
46
+ def space
47
+ fetch(space_key)
48
+ end
49
+
50
+ private
51
+
52
+ attr_reader :creds, :environment
53
+
54
+ def production?
55
+ environment == 'production'
56
+ end
57
+
58
+ def fetch(key)
59
+ creds.fetch(key)
60
+ rescue KeyError => e
61
+ raise CredentialKeyError, e
62
+ end
63
+
64
+ def correctly_formatted_domain_and_routes?(deploy_environment)
65
+ routes_hash = fetch(deploy_environment)
66
+ domains = routes_hash.keys
67
+ domains.each { |domain| correctly_formatted_domain?(domain, routes_hash) }
68
+ end
69
+
70
+ def correctly_formatted_domain?(domain, routes_hash)
71
+ raise 'Each domain in credentials must be a single string.' unless domain.is_a? String
72
+ raise "Domain #{domain} in credentials must contain a web extension, e.g. '.com'." unless domain.include?('.')
73
+ raise "Did you mean to add a list of hosts for domain #{domain}? Check your credentials.yml." unless routes_hash[domain]
74
+ raise "Hosts in credentials must be nested as an array under the desired domain #{domain}." unless routes_hash[domain].is_a? Array
75
+ raise "Did you mean to provide a hostname for the domain #{domain}? Check your credentials.yml." if routes_hash[domain].any?(&:nil?)
76
+ end
77
+
78
+ def host_key
79
+ "#{environment}_host"
80
+ end
81
+
82
+ def space_key
83
+ "#{environment}_space"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,128 +1,10 @@
1
- require 'git'
2
- require_relative 'git_hub_repository'
3
- require_relative 'remote_yaml_credential_provider'
4
-
5
1
  module Bookbinder
6
2
  class Configuration
7
3
 
8
4
  CURRENT_SCHEMA_VERSION = '1.0.0'
9
5
  STARTING_SCHEMA_VERSION = '1.0.0'
10
6
 
11
- CredentialKeyError = Class.new(StandardError)
12
- ConfigSchemaUnsupportedError = Class.new(StandardError)
13
-
14
- class AwsCredentials
15
- REQUIRED_KEYS = %w(access_key secret_key green_builds_bucket)
16
-
17
- def initialize(cred_hash)
18
- @creds = cred_hash
19
- end
20
-
21
- REQUIRED_KEYS.each do |method_name|
22
- define_method(method_name) do
23
- begin
24
- creds.fetch(method_name)
25
- rescue KeyError => e
26
- raise CredentialKeyError, e
27
- end
28
- end
29
- end
30
-
31
- private
32
-
33
- attr_reader :creds
34
- end
35
-
36
- class CfCredentials
37
- REQUIRED_KEYS = %w(api_endpoint organization app_name)
38
-
39
- def initialize(cred_hash, environment)
40
- @creds = cred_hash
41
- @environment = environment
42
- end
43
-
44
- REQUIRED_KEYS.each do |method_name|
45
- define_method(method_name) do
46
- fetch(method_name)
47
- end
48
- end
49
-
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.'
72
- end
73
- end
74
-
75
- def routes
76
- fetch(host_key) if correctly_formatted_domain_and_routes?(host_key)
77
- end
78
-
79
- def flat_routes
80
- routes.reduce([]) do |all_routes, domain_apps|
81
- domain, apps = domain_apps
82
- all_routes + apps.map { |app| [domain, app] }
83
- end
84
- end
85
-
86
- def space
87
- fetch(space_key)
88
- end
89
-
90
- private
91
-
92
- attr_reader :creds, :environment
93
-
94
- def production?
95
- environment == 'production'
96
- end
97
-
98
- def fetch(key)
99
- creds.fetch(key)
100
- rescue KeyError => e
101
- raise CredentialKeyError, e
102
- end
103
-
104
- def correctly_formatted_domain_and_routes?(deploy_environment)
105
- routes_hash = fetch(deploy_environment)
106
- domains = routes_hash.keys
107
- domains.each { |domain| correctly_formatted_domain?(domain, routes_hash) }
108
- end
109
-
110
- def correctly_formatted_domain?(domain, routes_hash)
111
- raise 'Each domain in credentials must be a single string.' unless domain.is_a? String
112
- raise "Domain #{domain} in credentials must contain a web extension, e.g. '.com'." unless domain.include?('.')
113
- raise "Did you mean to add a list of hosts for domain #{domain}? Check your credentials.yml." unless routes_hash[domain]
114
- raise "Hosts in credentials must be nested as an array under the desired domain #{domain}." unless routes_hash[domain].is_a? Array
115
- raise "Did you mean to provide a hostname for the domain #{domain}? Check your credentials.yml." if routes_hash[domain].any?(&:nil?)
116
- end
117
-
118
- def host_key
119
- "#{environment}_host"
120
- end
121
-
122
- def space_key
123
- "#{environment}_space"
124
- end
125
- end
7
+ ConfigSchemaUnsupportedError = Class.new(RuntimeError)
126
8
 
127
9
  attr_reader :schema_version, :schema_major_version, :schema_minor_version, :schema_patch_version
128
10
 
@@ -132,7 +14,7 @@ module Bookbinder
132
14
  end
133
15
 
134
16
  CONFIG_REQUIRED_KEYS = %w(book_repo public_host)
135
- CONFIG_OPTIONAL_KEYS = %w(archive_menu layout_repo versions pdf_index cred_repo pdf)
17
+ CONFIG_OPTIONAL_KEYS = %w(archive_menu layout_repo versions cred_repo)
136
18
 
137
19
  CONFIG_REQUIRED_KEYS.each do |method_name|
138
20
  define_method(method_name) do
@@ -162,32 +44,14 @@ module Bookbinder
162
44
  config.fetch('template_variables', {})
163
45
  end
164
46
 
165
- def aws_credentials
166
- @aws_creds ||= AwsCredentials.new(credentials.fetch('aws'))
167
- end
168
-
169
- def cf_credentials(environment)
170
- CfCredentials.new(credentials.fetch('cloud_foundry'), environment)
171
- end
172
-
173
47
  def ==(o)
174
- (o.class == self.class) && (o.config == self.config)
48
+ o.class == self.class && o.instance_variable_get(:@config) == @config
175
49
  end
176
50
 
177
51
  alias_method :eql?, :==
178
52
 
179
- protected
180
-
181
- attr_reader :config
182
-
183
53
  private
184
54
 
185
- def credentials
186
- @credentials ||= RemoteYamlCredentialProvider.new(@logger, credentials_repository).credentials
187
- end
188
-
189
- def credentials_repository
190
- @credentials_repository ||= GitHubRepository.new(logger: @logger, full_name: cred_repo, git_accessor: Git)
191
- end
55
+ attr_reader :config
192
56
  end
193
57
  end