bookbindery 8.5.0 → 9.0.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/bookbinder.gemspec +1 -1
- data/lib/bookbinder/cli.rb +36 -55
- data/lib/bookbinder/commands/bind.rb +3 -19
- data/lib/bookbinder/commands/collection.rb +33 -73
- data/lib/bookbinder/commands/components/command_options.rb +3 -22
- data/lib/bookbinder/commands/generate.rb +0 -11
- data/lib/bookbinder/commands/imprint.rb +3 -10
- data/lib/bookbinder/commands/punch.rb +0 -11
- data/lib/bookbinder/commands/update_local_doc_repos.rb +1 -9
- data/lib/bookbinder/commands/watch.rb +1 -10
- data/lib/bookbinder/config/fetcher.rb +2 -18
- data/lib/bookbinder/preprocessing/dita_html_preprocessor.rb +3 -6
- data/lib/bookbinder/preprocessing/dita_pdf_preprocessor.rb +3 -5
- data/lib/bookbinder/terminal.rb +0 -1
- metadata +3 -31
- data/lib/bookbinder/cf_command_runner.rb +0 -123
- data/lib/bookbinder/command_runner.rb +0 -23
- data/lib/bookbinder/command_validator.rb +0 -51
- data/lib/bookbinder/commands/build_and_push_tarball.rb +0 -38
- data/lib/bookbinder/commands/chain.rb +0 -11
- data/lib/bookbinder/commands/help.rb +0 -70
- data/lib/bookbinder/commands/naming.rb +0 -29
- data/lib/bookbinder/commands/push_from_local.rb +0 -132
- data/lib/bookbinder/commands/push_to_prod.rb +0 -66
- data/lib/bookbinder/commands/run_publish_ci.rb +0 -37
- data/lib/bookbinder/commands/version.rb +0 -29
- data/lib/bookbinder/config/aws_credentials.rb +0 -21
- data/lib/bookbinder/config/cf_credentials.rb +0 -62
- data/lib/bookbinder/config/remote_yaml_credential_provider.rb +0 -22
- data/lib/bookbinder/deploy/app_fetcher.rb +0 -36
- data/lib/bookbinder/deploy/archive.rb +0 -102
- data/lib/bookbinder/deploy/artifact.rb +0 -26
- data/lib/bookbinder/deploy/blue_green_app.rb +0 -29
- data/lib/bookbinder/deploy/cf_routes.rb +0 -32
- data/lib/bookbinder/deploy/deployment.rb +0 -55
- data/lib/bookbinder/deploy/distributor.rb +0 -76
- data/lib/bookbinder/deploy/failure.rb +0 -15
- data/lib/bookbinder/deploy/pusher.rb +0 -34
- data/lib/bookbinder/deploy/success.rb +0 -16
- data/lib/bookbinder/deprecated_logger.rb +0 -33
- data/lib/bookbinder/errors/cli_error.rb +0 -6
- data/lib/bookbinder/legacy/cli.rb +0 -71
- data/lib/bookbinder/preprocessing/dita_preprocessor.rb +0 -17
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'ansi/code'
|
3
|
-
|
4
|
-
module Bookbinder
|
5
|
-
module Config
|
6
|
-
class RemoteYamlCredentialProvider
|
7
|
-
def initialize(logger, version_control_system)
|
8
|
-
@logger = logger
|
9
|
-
@version_control_system = version_control_system
|
10
|
-
end
|
11
|
-
|
12
|
-
def credentials(repo_url)
|
13
|
-
logger.log "Processing #{ANSI.cyan{repo_url}}"
|
14
|
-
YAML.load(version_control_system.read_file("credentials.yml", from_repo: repo_url))
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
attr_reader :logger, :version_control_system
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require_relative 'blue_green_app'
|
2
|
-
require_relative 'cf_routes'
|
3
|
-
|
4
|
-
module Bookbinder
|
5
|
-
module Deploy
|
6
|
-
class AppFetcher
|
7
|
-
def initialize(routes_to_search, cf_command_runner)
|
8
|
-
@routes_to_search = routes_to_search
|
9
|
-
@cf_command_runner = cf_command_runner
|
10
|
-
end
|
11
|
-
|
12
|
-
def fetch_current_app
|
13
|
-
raw_cf_routes = cf_command_runner.cf_routes_output
|
14
|
-
cf_routes = CfRoutes.new(raw_cf_routes)
|
15
|
-
|
16
|
-
existing_hosts = routes_to_search.select do |domain, host|
|
17
|
-
cf_routes.apps_by_host_and_domain.has_key?([host, domain])
|
18
|
-
end
|
19
|
-
|
20
|
-
return nil if existing_hosts.empty?
|
21
|
-
app_groups = existing_hosts.map { |domain, host| apps_for_host(cf_routes, domain, host) }
|
22
|
-
apps_for_existing_routes = app_groups.first
|
23
|
-
apps_for_existing_routes.first
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
attr_reader :routes_to_search, :cf_command_runner
|
29
|
-
|
30
|
-
def apps_for_host(routes_from_cf, domain, host)
|
31
|
-
routes_from_cf.apps_by_host_and_domain.fetch([host, domain], []).
|
32
|
-
map &BlueGreenApp.method(:new)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'fog/aws'
|
2
|
-
require 'tmpdir'
|
3
|
-
require_relative '../deprecated_logger'
|
4
|
-
require_relative 'artifact'
|
5
|
-
require_relative 'success'
|
6
|
-
|
7
|
-
module Bookbinder
|
8
|
-
module Deploy
|
9
|
-
class Archive
|
10
|
-
class FileDoesNotExist < StandardError; end
|
11
|
-
class NoNamespaceGiven < StandardError; end
|
12
|
-
|
13
|
-
def initialize(logger: nil, key: '', secret: '')
|
14
|
-
@logger = logger
|
15
|
-
@aws_key = key
|
16
|
-
@aws_secret_key = secret
|
17
|
-
end
|
18
|
-
|
19
|
-
def create_and_upload_tarball(
|
20
|
-
app_dir: 'final_app',
|
21
|
-
bucket: '',
|
22
|
-
build_number: nil,
|
23
|
-
namespace: nil
|
24
|
-
)
|
25
|
-
tarball_filename, tarball_path = create_tarball(app_dir, build_number, namespace)
|
26
|
-
upload_file(bucket, tarball_filename, tarball_path)
|
27
|
-
Success.new("Green build ##{build_number} has been uploaded to S3 for #{namespace}")
|
28
|
-
end
|
29
|
-
|
30
|
-
def upload_file(bucket, name, source_path)
|
31
|
-
find_or_create_directory(bucket).
|
32
|
-
files.create(key: name,
|
33
|
-
body: File.read(source_path),
|
34
|
-
public: true)
|
35
|
-
end
|
36
|
-
|
37
|
-
def download(download_dir: nil, bucket: nil, build_number: nil, namespace: nil)
|
38
|
-
raise NoNamespaceGiven, 'One must specify a namespace to find files in this bucket' unless namespace
|
39
|
-
|
40
|
-
directory = connection.directories.get bucket
|
41
|
-
build_number ||= latest_build_number_for_namespace(directory, namespace)
|
42
|
-
filename = Artifact.new(namespace, build_number, 'tgz').filename
|
43
|
-
|
44
|
-
s3_file = directory.files.get(filename)
|
45
|
-
raise FileDoesNotExist, "Unable to find tarball on AWS for book '#{namespace}', build number: #{build_number}" unless s3_file
|
46
|
-
|
47
|
-
downloaded_file = File.join(Dir.mktmpdir, 'downloaded.tgz')
|
48
|
-
File.open(downloaded_file, 'wb') { |f| f.write(s3_file.body) }
|
49
|
-
Dir.chdir(download_dir) { `tar xzf #{downloaded_file}` }
|
50
|
-
|
51
|
-
@logger.log "Green build ##{build_number.to_s.green} has been downloaded from S3 and untarred into #{download_dir.to_s.cyan}"
|
52
|
-
end
|
53
|
-
|
54
|
-
def tarball_name_regex(namespace)
|
55
|
-
/^#{namespace}-(\d+_?\d*)\.tgz/
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def find_or_create_directory(name)
|
61
|
-
connection.directories.create(key: name)
|
62
|
-
rescue Excon::Errors::Conflict
|
63
|
-
connection.directories.get(name)
|
64
|
-
end
|
65
|
-
|
66
|
-
def create_tarball(app_dir, build_number, namespace)
|
67
|
-
tarball_filename = Artifact.new(namespace, build_number, 'tgz').filename
|
68
|
-
tarball_path = File.join(Dir.mktmpdir, tarball_filename)
|
69
|
-
|
70
|
-
Dir.chdir(app_dir) { `tar czf #{tarball_path} *` }
|
71
|
-
return tarball_filename, tarball_path
|
72
|
-
end
|
73
|
-
|
74
|
-
def latest_build_number_for_namespace(directory, namespace)
|
75
|
-
all_files = all_files_workaround_for_fog_map_limitation(directory.files)
|
76
|
-
|
77
|
-
all_files_with_namespace = all_files.map do |file|
|
78
|
-
filename = file.key
|
79
|
-
file if filename[tarball_name_regex(namespace)]
|
80
|
-
end.compact
|
81
|
-
|
82
|
-
return nil if all_files_with_namespace.empty?
|
83
|
-
most_recent_file = all_files_with_namespace.sort_by { |file| file.last_modified }.last
|
84
|
-
|
85
|
-
most_recent_filename = most_recent_file.key
|
86
|
-
most_recent_filename[tarball_name_regex(namespace), 1]
|
87
|
-
end
|
88
|
-
|
89
|
-
def connection
|
90
|
-
@connection ||= Fog::Storage.new :provider => 'AWS',
|
91
|
-
:aws_access_key_id => @aws_key,
|
92
|
-
:aws_secret_access_key => @aws_secret_key
|
93
|
-
end
|
94
|
-
|
95
|
-
def all_files_workaround_for_fog_map_limitation(files)
|
96
|
-
all_files = []
|
97
|
-
files.each { |f| all_files << f }
|
98
|
-
all_files
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Bookbinder
|
2
|
-
module Deploy
|
3
|
-
class Artifact
|
4
|
-
attr_reader :namespace
|
5
|
-
|
6
|
-
def initialize(namespace, build_number, extension, path = '.')
|
7
|
-
@namespace = namespace
|
8
|
-
@build_number = build_number
|
9
|
-
@path = path
|
10
|
-
@extension = extension
|
11
|
-
end
|
12
|
-
|
13
|
-
def full_path
|
14
|
-
File.join(path, filename)
|
15
|
-
end
|
16
|
-
|
17
|
-
def filename
|
18
|
-
"#{namespace}-#{build_number}.#{extension}"
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
attr_reader :build_number, :path, :extension
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Bookbinder
|
2
|
-
module Deploy
|
3
|
-
class BlueGreenApp
|
4
|
-
def initialize(name)
|
5
|
-
@name = name.strip
|
6
|
-
end
|
7
|
-
|
8
|
-
def ==(other)
|
9
|
-
to_s == other.to_s
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
name
|
14
|
-
end
|
15
|
-
|
16
|
-
def with_flipped_name
|
17
|
-
if name.match(/green$/)
|
18
|
-
BlueGreenApp.new(name.sub(/green$/, 'blue'))
|
19
|
-
else
|
20
|
-
BlueGreenApp.new(name.sub(/blue$/, 'green'))
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
attr_reader :name
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Bookbinder
|
2
|
-
module Deploy
|
3
|
-
class CfRoutes
|
4
|
-
def initialize(raw_routes)
|
5
|
-
@raw_routes = raw_routes
|
6
|
-
end
|
7
|
-
|
8
|
-
def apps_by_host_and_domain
|
9
|
-
@apps_by_host_and_domain ||= data(raw_routes).reduce({}) {|acc, row|
|
10
|
-
parsed_row = Hash[headers(raw_routes).zip(row)]
|
11
|
-
acc.merge(parsed_row.values_at('host', 'domain') => parse_apps(parsed_row['apps']))
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
attr_reader :raw_routes
|
18
|
-
|
19
|
-
def parse_apps(apps)
|
20
|
-
apps.split(',').map(&:strip) unless apps.nil?
|
21
|
-
end
|
22
|
-
|
23
|
-
def headers(raw)
|
24
|
-
raw.lines[2].split(/\s+/)
|
25
|
-
end
|
26
|
-
|
27
|
-
def data(raw)
|
28
|
-
raw.lines[3..-1].map {|line| line.split(/\s+/, headers(raw).size)}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Bookbinder
|
2
|
-
module Deploy
|
3
|
-
class Deployment
|
4
|
-
attr_reader :app_dir, :build_number, :cf_credentials
|
5
|
-
|
6
|
-
def initialize(app_dir: nil,
|
7
|
-
aws_credentials: nil,
|
8
|
-
book_repo: nil,
|
9
|
-
build_number: nil,
|
10
|
-
cf_credentials: nil)
|
11
|
-
@app_dir = app_dir
|
12
|
-
@aws_credentials = aws_credentials
|
13
|
-
@book_repo = book_repo
|
14
|
-
@build_number = build_number
|
15
|
-
@cf_credentials = cf_credentials
|
16
|
-
end
|
17
|
-
|
18
|
-
def artifact_filename
|
19
|
-
artifact.filename
|
20
|
-
end
|
21
|
-
|
22
|
-
def artifact_full_path
|
23
|
-
artifact.full_path
|
24
|
-
end
|
25
|
-
|
26
|
-
def aws_access_key
|
27
|
-
aws_credentials.access_key
|
28
|
-
end
|
29
|
-
|
30
|
-
def aws_secret_key
|
31
|
-
aws_credentials.secret_key
|
32
|
-
end
|
33
|
-
|
34
|
-
def flat_routes
|
35
|
-
cf_credentials.flat_routes
|
36
|
-
end
|
37
|
-
|
38
|
-
def green_builds_bucket
|
39
|
-
aws_credentials.green_builds_bucket
|
40
|
-
end
|
41
|
-
|
42
|
-
def namespace
|
43
|
-
Ingest::DestinationDirectory.new(book_repo)
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
attr_reader :aws_credentials, :book_repo
|
49
|
-
|
50
|
-
def artifact
|
51
|
-
Artifact.new(namespace, build_number, 'log', '/tmp')
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require_relative '../cf_command_runner'
|
2
|
-
require_relative '../ingest/destination_directory'
|
3
|
-
require_relative '../sheller'
|
4
|
-
require_relative 'app_fetcher'
|
5
|
-
require_relative 'archive'
|
6
|
-
require_relative 'artifact'
|
7
|
-
require_relative 'pusher'
|
8
|
-
|
9
|
-
module Bookbinder
|
10
|
-
module Deploy
|
11
|
-
class Distributor
|
12
|
-
EXPIRATION_HOURS = 2
|
13
|
-
|
14
|
-
def self.build(streams, archive, deployment)
|
15
|
-
cf_command_runner = CfCommandRunner.new(streams, Sheller.new, deployment.cf_credentials, deployment.artifact_full_path)
|
16
|
-
cf_app_fetcher = AppFetcher.new(deployment.flat_routes, cf_command_runner)
|
17
|
-
pusher = Pusher.new(cf_command_runner, cf_app_fetcher)
|
18
|
-
new(streams, archive, pusher, deployment)
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(streams, archive, pusher, deployment)
|
22
|
-
@streams = streams
|
23
|
-
@archive = archive
|
24
|
-
@pusher = pusher
|
25
|
-
@deployment = deployment
|
26
|
-
end
|
27
|
-
|
28
|
-
def distribute
|
29
|
-
push_app
|
30
|
-
nil
|
31
|
-
rescue => e
|
32
|
-
streams[:err].puts(<<-ERROR.chomp)
|
33
|
-
[ERROR] #{e.message}
|
34
|
-
[DEBUG INFO]
|
35
|
-
CF organization: #{cf_credentials.organization}
|
36
|
-
CF space: #{cf_credentials.space}
|
37
|
-
CF account: #{cf_credentials.username}
|
38
|
-
routes: #{cf_credentials.routes}
|
39
|
-
ERROR
|
40
|
-
raise
|
41
|
-
ensure
|
42
|
-
upload_trace
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
attr_reader :archive, :deployment, :pusher, :streams
|
48
|
-
|
49
|
-
def push_app
|
50
|
-
pusher.push(deployment.app_dir)
|
51
|
-
end
|
52
|
-
|
53
|
-
def upload_trace
|
54
|
-
uploaded_file = archive.upload_file(deployment.green_builds_bucket, deployment.artifact_filename, deployment.artifact_full_path)
|
55
|
-
log_success(
|
56
|
-
["Your cf trace file is available at: #{uploaded_file.url(Time.now.to_i + EXPIRATION_HOURS*60*60)}",
|
57
|
-
"This URL will expire in #{EXPIRATION_HOURS} hours, so if you need to share it, make sure to save a copy now."]
|
58
|
-
)
|
59
|
-
rescue Errno::ENOENT
|
60
|
-
log_error("Could not find CF trace file: #{deployment.artifact_full_path}")
|
61
|
-
end
|
62
|
-
|
63
|
-
def cf_credentials
|
64
|
-
deployment.cf_credentials
|
65
|
-
end
|
66
|
-
|
67
|
-
def log_success(message)
|
68
|
-
streams[:success].puts(message)
|
69
|
-
end
|
70
|
-
|
71
|
-
def log_error(message)
|
72
|
-
streams[:err].puts(message)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Bookbinder
|
2
|
-
module Deploy
|
3
|
-
class Pusher
|
4
|
-
def initialize(cf_cli, app_fetcher)
|
5
|
-
@cf_cli = cf_cli
|
6
|
-
@app_fetcher = app_fetcher
|
7
|
-
end
|
8
|
-
|
9
|
-
def push(app_dir)
|
10
|
-
Dir.chdir(app_dir) do
|
11
|
-
cf_cli.login
|
12
|
-
|
13
|
-
old_app = app_fetcher.fetch_current_app
|
14
|
-
|
15
|
-
if old_app
|
16
|
-
new_app = old_app.with_flipped_name
|
17
|
-
cf_cli.start(new_app)
|
18
|
-
cf_cli.push(new_app)
|
19
|
-
cf_cli.map_routes(new_app)
|
20
|
-
cf_cli.takedown_old_target_app(old_app)
|
21
|
-
else
|
22
|
-
new_app = cf_cli.new_app
|
23
|
-
cf_cli.push(new_app)
|
24
|
-
cf_cli.map_routes(new_app)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
attr_reader :cf_cli, :app_fetcher
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|