lib/locomotive/wagon/commands/push_command.rb
require 'locomotive/steam'
require_relative 'loggers/push_logger'
require_relative_all 'concerns'
require_relative_all '../decorators/concerns'
require_relative_all '../decorators'
require_relative '../tools/glob'
require_relative 'push_sub_commands/push_base_command'
require_relative_all 'push_sub_commands'
module Locomotive::Wagon
class PushCommand < Struct.new(:env, :path, :options, :shell)
RESOURCES = %w(site content_types content_entries pages snippets sections theme_assets translations).freeze
RESOURCES_WITH_CONTENT = %w(content_entries translations).freeze
include ApiConcern
include NetrcConcern
include DeployFileConcern
include SteamConcern
include InstrumentationConcern
include SpinnerConcern
attr_accessor :platform_url, :credentials
def self.push(env, path, options, shell)
self.new(env, path, options, shell).push
end
def push
require 'haml'
Locomotive::Wagon.require_misc_gems
api_client = build_api_site_client(connection_information)
return if api_client.nil?
# Ask for a confirmation (Warning) if we deploy with the -d option
# since it alters content on the remote engine
if options[:data]
return unless ask_for_performing("Warning! You're about to deploy data which will alter the content of your site.")
end
if options[:verbose]
PushLogger.new
_push(api_client)
else
show_wait_spinner('Deploying...') { _push(api_client) }
end
end
private
def _push(api_client)
validate!
content_assets_pusher = Locomotive::Wagon::PushContentAssetsCommand.new(api_client, steam_services)
each_resource do |klass|
klass.push(api_client, steam_services, content_assets_pusher, remote_site) do |pusher|
pusher.with_data if options[:data]
pusher.only(options[:filter]) unless options[:filter].blank?
end
end
print_result_message
end
# To push all the other resources, the big requirement is to
# have the same locales between the local site and the remote one.
def validate!
if local_site.default_locale != remote_site.default_locale && remote_site.edited?
raise "Your Wagon site locale (#{local_site.default_locale}) is not the same as the one in the back-office (#{remote_site.default_locale})."
end
if local_site.locales != remote_site.locales
instrument :warning, message: "Your Wagon site locales (#{local_site.locales.join(', ')}) are not the same as the ones in the back-office (#{remote_site.locales.join(', ')})."
end
end
def each_resource
RESOURCES.each do |name|
next if !options[:resources].blank? && !options[:resources].include?(name)
next if RESOURCES_WITH_CONTENT.include?(name) && !options[:data]
klass = "Locomotive::Wagon::Push#{name.camelcase}Command".constantize
yield klass
end
end
def connection_information
if information = read_deploy_settings(self.env, self.path)
# the deployment env exists and contains all the information we need to move on
information
else
# warn the user that we're going to create a new site. Ask her/him if we continue
return unless ask_for_performing('You are about to deploy a new site')
# mandatory to sign in
load_credentials_from_netrc
return if self.credentials.nil?
# create the remote site on the platform
site = create_remote_site
# update the deploy.yml by adding the new env since we've got all the information
write_deploy_settings(self.env, self.path, {
'host' => api_host,
'handle' => site.handle,
'email' => credentials[:email],
'api_key' => credentials[:api_key]
}.tap { |options| options['ssl'] = true if api_host.ends_with?(':443') })
end
end
def create_remote_site
# get an instance of the Steam services in order to load the information about the site (SiteRepository)
steam_services.current_site.tap do |site|
# ask for a handle if not found (blank: random one)
if (handle = shell.try(:ask, "What is the handle of your site? (default: a random one)")).present?
site[:handle] = handle
end
# create the site
attributes = SiteDecorator.new(site).to_hash
_site = api_client.sites.create(attributes)
site[:handle] = _site.handle
instrument :site_created, site: site
end
end
def load_credentials_from_netrc
# ask for the platform URL (or LOCOMOTIVE_PLATFORM_URL env variable)
ask_for_platform_url
# retrieve email + api_key. If no entry present in the .netrc, raise an error
self.credentials = read_credentials_from_netrc(self.api_host)
if self.credentials.nil?
shell.say "Sorry, we were unable to find the credentials for this platform.\nPlease first login using the \"bundle exec wagon auth\"", :yellow
end
end
def ask_for_platform_url
default = ENV['LOCOMOTIVE_PLATFORM_URL'] || DEFAULT_PLATFORM_URL
url = shell.try(:ask, "What is the URL of your platform? (default: #{default})")
self.platform_url = url.blank? ? default : url
end
def local_site
return @local_site if @local_site
@local_site = SiteDecorator.new(steam_services.repositories.site.first)
end
def remote_site
return @remote_site if @remote_site
attribute = nil
begin
attributes = @api_site_client.current_site.get.attributes
rescue Locomotive::Coal::UnknownResourceError
shell.say 'Sorry, we were unable to find your site on the remote platform. Check the information in your config/deploy.yml file.', :red
raise 'Unable to find your site on the remote platform'
end
_site = Locomotive::Steam::Site.new(attributes)
@remote_site = RemoteSiteDecorator.new(_site)
end
def ask_for_performing(message)
shell.say(message, :yellow)
unless shell.yes?("Are you sure you want to perform this action? (answer yes or no)")
shell.say("Deployment canceled!", :yellow)
return false
end
true
end
def print_result_message
shell.say "\n\nYour site has been deployed.", :green
if remote_site.respond_to?(:preview_url)
shell.say "\nTo preview your site, visit: #{remote_site.preview_url.light_white}"
end
if remote_site.respond_to?(:sign_in_url)
shell.say "To edit the content of your site, visit: #{remote_site.sign_in_url.light_white}"
end
true
end
end
end