phase 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd754d7a55b13fc301cbf943586379f608d148e4
4
- data.tar.gz: 681b6d02ee212ba1c8c45dcf98f22cfc62bdfc36
3
+ metadata.gz: c0e05d1823d6db24fc626a2401e46661cc90f5ce
4
+ data.tar.gz: ed876996eda29eba97b94d827df8119d6cab93d7
5
5
  SHA512:
6
- metadata.gz: 0fde26b95c1f6e39ead11f894bea20634623d2d8de78e5f7485705e1a491dd111ade3f1103b3b77beea42ffb4481e89421c920ba0d413168d18a8b9624da34a5
7
- data.tar.gz: 2df205c7237088708b851097bf7630731870a8e4d810d6c60c2cb35b0247794a6ce8fb391cdacd2b196d63b898ae343776e07d58cb95bfef97b5fe7a714857a7
6
+ metadata.gz: 9b6ab4a3dc89082fc6b769d5d5b302e7288ba6083312f8523118425721322949b8dca51bca9dbe1ae720285e76b2a228f4897040bf11e6c625b209c49f0d3904
7
+ data.tar.gz: 8ae0ec1e4d1a2b1267c9d4bf7445ddf4464bf45f296258b02e03bb416c360832c2208c74642a0ce24092004d04f223ca06ca3f6828399c6a7b18c55f5772429f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
@@ -3,6 +3,15 @@ module Phase
3
3
  module AWS
4
4
  class Server < ::Phase::Adapters::Abstract::Server
5
5
 
6
+ attr_accessor :username
7
+
8
+ def to_host_hash(host_method)
9
+ {
10
+ user: username,
11
+ hostname: resource.__send__(host_method)
12
+ }
13
+ end
14
+
6
15
  class << self
7
16
  # @return [Array<AWS::Server>] All known EC2 instances
8
17
  def all
@@ -15,6 +24,8 @@ module Phase
15
24
  new(api.servers.get(instance_id))
16
25
  end
17
26
 
27
+ # Finds servers through the provided filter options.
28
+ #
18
29
  # @param [Hash] options Filtering options
19
30
  # @option options [String] :vpc_id The ID of a VPC
20
31
  # @option options [String] :name The value of the 'Name' tag
@@ -26,13 +37,12 @@ module Phase
26
37
  def where(options = {})
27
38
  filters = {}
28
39
 
29
- filters["vpc-id"] = options.delete(:vpc_id) if options[:vpc_id]
30
- filters["tag:Name"] = options.delete(:name) if options[:name]
31
- filters["instance-ids"] = options.delete(:ids) if options[:ids]
32
- filters["subnet-id"] = options.delete(:subnet_id) if options[:subnet_id]
33
-
34
- filters["tag:Role"] = options.delete(:role) if options[:role]
35
- filters["tag:Environment"] = options.delete(:environment) if options[:environment]
40
+ filters["vpc-id"] = options.delete(:vpc_id) if options.has_key?(:vpc_id)
41
+ filters["tag:Name"] = options.delete(:name) if options.has_key?(:name)
42
+ filters["instance-ids"] = options.delete(:ids) if options.has_key?(:ids)
43
+ filters["subnet-id"] = options.delete(:subnet_id) if options.has_key?(:subnet_id)
44
+ filters["tag:Role"] = options.delete(:role) if options.has_key?(:role)
45
+ filters["tag:Environment"] = options.delete(:environment) if options.has_key?(:environment)
36
46
 
37
47
  if options.any?
38
48
  raise ArgumentError, "Unknown filters '#{options.keys.join(", ")}'!"
data/lib/phase/cli/all.rb CHANGED
@@ -1,9 +1,9 @@
1
- require "phase/cli/mixins/loggable"
2
-
3
1
  require "phase/cli/command"
4
2
 
5
3
  require "phase/cli/env"
4
+ require "phase/cli/deploy"
6
5
  require "phase/cli/keys"
6
+ require "phase/cli/ipa"
7
7
  require "phase/cli/logs"
8
8
  require "phase/cli/ssh"
9
9
  require "phase/cli/mosh"
@@ -1,6 +1,7 @@
1
1
  module Phase
2
2
  module CLI
3
3
  class Command
4
+ include ::Phase::Util::Console
4
5
 
5
6
  class << self
6
7
  include ::Commander::Methods
@@ -0,0 +1,36 @@
1
+ module Phase
2
+ module CLI
3
+ class Deploy < Command
4
+
5
+ command :deploy do |c|
6
+ c.syntax = "phase deploy <environment>"
7
+
8
+ c.description = <<-EOS.strip_heredoc
9
+ Builds and deploys code to the specified <environment>. <environment> may be
10
+ any environment configured in the Phasefile.
11
+ EOS
12
+
13
+ c.action do |args, options|
14
+ new(args, options).run
15
+ end
16
+ end
17
+
18
+ attr_reader :environment
19
+
20
+ def initialize(args, options)
21
+ @environment = args.first
22
+ super
23
+ end
24
+
25
+ def run
26
+ # load_environment_config
27
+ # create_build_dir
28
+ # shallow_clone_repository
29
+ # build_docker_image
30
+ # push_docker_image
31
+ # trigger_remote_deployment
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ module Phase
2
+ module CLI
3
+ class IPA < Command
4
+
5
+ command :ipa do |c|
6
+ c.syntax = "phase ipa [version_number] [filename|pattern]..."
7
+
8
+ c.description = <<-EOS.strip_heredoc
9
+ Generates enterprise distribution .plists for .ipa app bundles and uploads
10
+ all required files to the web for distribution.
11
+ EOS
12
+
13
+ c.action do |args, options|
14
+ new(args, options).run
15
+ end
16
+ end
17
+
18
+ attr_accessor :version, :filenames
19
+
20
+ def initialize(args, options)
21
+ @version = args.shift
22
+ @filenames = args
23
+
24
+ if @version.blank? || @filenames.blank?
25
+ fail "invalid syntax: phase ipa [--version version_number] [filename|glob_pattern]..."
26
+ end
27
+
28
+ if Phase.config.bundle_id_prefix.blank?
29
+ fail "missing setting: set `Phase.config.bundle_id_prefix = [PREFIX] in Phasefile"
30
+ elsif Phase.config.ipa_bucket_name.blank?
31
+ fail "missing setting: set `Phase.config.ipa_bucket_name = [BUCKET]` in Phasefile"
32
+ elsif Phase.config.ipa_directory_prefix.blank?
33
+ fail "missing setting: set `Phase.config.ipa_directory_prefix = [PREFIX] in Phasefile"
34
+ end
35
+
36
+ super
37
+ end
38
+
39
+ def run
40
+ deployment = ::Phase::IPA::EnterpriseDeployment.new(version, *filenames)
41
+ deployment.run!
42
+ end
43
+
44
+ end
45
+ end
46
+ end
data/lib/phase/cli/ssh.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  module Phase
2
2
  module CLI
3
3
  class SSH < Command
4
- include Mixins::Loggable
5
-
6
4
  command :ssh do |c|
7
5
  c.syntax = "phase ssh [-i instance_id] [-n instance_name] [-r instance_role] [-u user] [-c conn_str] [username@instance_name|instance_id]"
8
6
 
@@ -1,45 +1,49 @@
1
1
  module Phase
2
2
  class Configuration
3
3
 
4
- attr_accessor :use_bastions,
5
- :bastion_role,
6
- :bastion_user,
7
-
8
- :aws_region,
9
-
10
- :adapter
4
+ attr_accessor :bastions_enabled, :bastion_role, :bastion_user, :public_subnet_name,
5
+ :private_subnet_name, :aws_region, :adapter, :backend,
6
+ :bundle_id_prefix, :ipa_directory_prefix, :ipa_bucket_name
11
7
 
12
8
  def initialize
13
- @use_bastions = false
14
- @bastion_role = "ssh"
15
- @bastion_user = "orca"
16
-
17
- @aws_region = "us-east-1"
18
-
19
- @adapter = ::Phase::Adapters::AWS
20
-
21
- ::SSHKit.config.backend = SSH::Backend
22
-
23
- configure_from_yml if defined?(::Rails) && yml_present?
9
+ @bastions_enabled = false
10
+ @bastion_role = nil
11
+ @bastion_user = nil
12
+ @public_subnet_name = "public"
13
+ @private_subnet_name = "private"
14
+ @aws_region = "us-east-1"
15
+ @adapter = ::Phase::Adapters::AWS
16
+
17
+ @bundle_id_prefix = ""
18
+ @ipa_directory_prefix = ""
19
+ @ipa_bucket_name = ""
20
+
21
+ self.backend = ::Phase::SSH::Backend
22
+ set_aws_credentials!
24
23
  end
25
24
 
26
- def configure_from_yml
27
- yml_config = ::YAML.load_file(yml_path) || {}
28
-
29
- @use_bastions = yml_config[:use_bastions] if yml_config.has_key(:use_bastions)
30
- @bastion_role = yml_config[:bastion_role] if yml_config.has_key(:bastion_role)
31
- @bastion_user = yml_config[:bastion_user] if yml_config.has_key(:bastion_user)
32
-
33
- @aws_region = yml_config[:aws_region] if yml_config.has_key(:aws_region)
25
+ def backend=(backend)
26
+ @backend = backend
27
+ ::SSHKit.config.backend = @backend
34
28
  end
35
29
 
36
- def yml_present?
37
- File.exists?(yml_path)
30
+ def load_phasefile!
31
+ if ::File.exist?(phasefile_path)
32
+ load phasefile_path
33
+ end
38
34
  end
39
35
 
40
- def yml_path
41
- # ::Rails.root.join("config", "phase.yml")
42
- ""
36
+ def set_aws_credentials!
37
+ Fog.credentials = {
38
+ aws_access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
39
+ aws_secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY')
40
+ }
43
41
  end
42
+
43
+ private
44
+
45
+ def phasefile_path
46
+ @phasefile_path ||= ::File.join(::Dir.pwd, 'Phasefile')
47
+ end
44
48
  end
45
49
  end
data/lib/phase/dsl.rb CHANGED
@@ -1,37 +1,31 @@
1
+ require 'sshkit/dsl'
2
+
1
3
  module Phase
2
4
  module DSL
3
5
 
4
- # @param [String] role_name The value of the 'Role' tag
5
- # @param [String] environment The value of the 'Environment' tag
6
- # @param [Hash] options SSHKit concurrency options
6
+ # Runs a command on servers with the given role.
7
+ #
8
+ # @param [String] role_name The value of the 'Role' tag. Can be nil
9
+ # @param [String] environment The value of the 'Environment' tag. Can be nil
10
+ # @param [Hash] options Query and concurrency options
11
+ # @option options [String] :bastion (true) Whether to connect through a bastion host
7
12
  # @see SSHKit::Coordinator for concurrency options
8
13
  # @return [void]
9
- def on_role(role_name, environment = "staging", options = {}, &block)
10
- servers = ::Phase.servers.where(role: role_name, environment: environment)
11
- on(servers.map {|s| s.resource.private_ip_address }, options, &block)
12
- end
13
-
14
- def on(destination_ips, options = {}, &block)
15
- server = ::Phase.servers.where(role: ::Phase.config.bastion_role).first
16
- raise ArgumentError, "no servers found" unless server
17
-
18
- # TODO: identify the CORRECT bastion host per subnet/network
19
- bastion_host = "#{ ::Phase.config.bastion_user }@#{ server.resource.dns_name }"
20
- coordinator = ::SSHKit::Coordinator.new(bastion_host)
21
-
22
- # TODO: clean up this logic. this should be done within a coordinator
23
- # (or elsewhere) so we can ID networks on a per-adapter basis
24
- results = Array(destination_ips).map do |ip|
25
- coordinator.each(options) do
26
- on_remote_host(ip) { instance_exec(&block) }
27
- end
14
+ def run_remotely(options = {}, &block)
15
+ filter_options = options.extract!(:role_name, :environment, :user)
16
+ servers = ::Phase.servers.where(filter_options)
17
+
18
+ if options.has_key?(:bastion) && bastion = options.delete(:bastion)
19
+ hosts = servers.map { |s| {user: options[:user], hostname: s.resource.private_ip_address} }
20
+ on_servers_through_bastion(bastion, servers, options, &block)
21
+ else
22
+ hosts = servers.map { |s| {user: options[:user], hostname: s.resource.dns_name} }
23
+ on(hosts, options, &block)
28
24
  end
29
-
30
- results.flatten
31
25
  end
32
26
 
33
- def run_locally(&block)
34
- ::SSHKit::Backend::Local.new(&block).run
27
+ def on_servers_through_bastion(bastion, servers, options = {}, &block)
28
+ ::Phase::Kit::SSH::BastionCoordinator.new(bastion, hosts).run!(options, &block)
35
29
  end
36
30
 
37
31
  end
@@ -0,0 +1,46 @@
1
+ module Phase
2
+ module Deploy
3
+
4
+ class Build
5
+ attr_reader :version_tag
6
+
7
+ def initialize(version_tag)
8
+ @version_tag = version_tag
9
+ end
10
+
11
+ def execute
12
+ build_image
13
+ tag_latest_image
14
+ push
15
+ end
16
+
17
+ private
18
+
19
+ def build_image
20
+ clear_build_dir
21
+ clone_clean_repo
22
+ system("docker build -t #{repo_name}:#{version_tag} .build/")
23
+ end
24
+
25
+ def tag_latest_image
26
+ system("docker tag #{repo_name}:#{version_tag} #{repo_name}:latest")
27
+ end
28
+
29
+ def push
30
+ system("docker push #{repo_name}:#{version_tag}")
31
+ end
32
+
33
+ def repo_name
34
+ ::Phase.config.docker_repository
35
+ end
36
+ end
37
+
38
+
39
+ class SandboxBuild < Build
40
+ def build
41
+ system(build_image_cmd)
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,26 @@
1
+ module Phase
2
+ module Deploy
3
+ class Deployment
4
+
5
+ # environment
6
+ # build options
7
+ # tag strategy
8
+ # server options
9
+ # environment name
10
+ # role name
11
+
12
+ attr_reader :build
13
+
14
+ def initialize(environment, options = {})
15
+ case environment
16
+ when :sandbox
17
+ self.build = SandboxBuild.new
18
+ else
19
+ self.build = Build.new
20
+ end
21
+
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,71 @@
1
+ module Phase
2
+ module IPA
3
+ class App
4
+ attr_reader :qualified_path, :name, :version
5
+ attr_accessor :download_url
6
+
7
+ def initialize(qualified_path, version)
8
+ @qualified_path, @version = qualified_path, version
9
+ @name = ::File.basename(qualified_path, ".ipa")
10
+ end
11
+
12
+ def ipa_filename
13
+ "#{bundle_name}-#{version}.ipa"
14
+ end
15
+
16
+ def plist_filename
17
+ "#{bundle_name}-#{version}.plist"
18
+ end
19
+
20
+ def plist_xml
21
+ <<-EOXML.strip_heredoc
22
+ <?xml version="1.0" encoding="UTF-8"?>
23
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
24
+ <plist version="1.0">
25
+ <dict>
26
+ <key>items</key>
27
+ <array>
28
+ <dict>
29
+ <key>assets</key>
30
+ <array>
31
+ <dict>
32
+ <key>kind</key>
33
+ <string>software-package</string>
34
+ <key>url</key>
35
+ <string>https://s3.amazonaws.com/orca-static-assets/apps/#{ipa_filename}</string>
36
+ </dict>
37
+ </array>
38
+ <key>metadata</key>
39
+ <dict>
40
+ <key>bundle-identifier</key>
41
+ <string>#{bundle_id_prefix}.#{bundle_name}</string>
42
+ <key>bundle-version</key>
43
+ <string>#{version}</string>
44
+ <key>kind</key>
45
+ <string>software</string>
46
+ <key>title</key>
47
+ <string>#{human_name}</string>
48
+ </dict>
49
+ </dict>
50
+ </array>
51
+ </dict>
52
+ </plist>
53
+ EOXML
54
+ end
55
+
56
+ private
57
+
58
+ def human_name
59
+ name.titleize
60
+ end
61
+
62
+ def bundle_name
63
+ name.camelize
64
+ end
65
+
66
+ def bundle_id_prefix
67
+ Phase.config.bundle_id_prefix
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,85 @@
1
+ module Phase
2
+ module IPA
3
+ class EnterpriseDeployment
4
+ include ::Phase::Util::Console
5
+
6
+ attr_reader :version, :file_paths, :aws, :bucket, :prefix, :apps
7
+
8
+ def initialize(version, *filenames)
9
+ @version = version
10
+ @file_paths = filenames.map do |name|
11
+ ::Dir.glob( ::File.expand_path(name) )
12
+ end
13
+
14
+ @file_paths.flatten!
15
+ @file_paths.uniq!
16
+
17
+ @aws = ::Fog::Storage::AWS.new(region: Phase.config.aws_region)
18
+ @bucket = aws.directories.get(Phase.config.ipa_bucket_name)
19
+ @prefix = ::Pathname.new(Phase.config.ipa_directory_prefix)
20
+
21
+ @apps = []
22
+ end
23
+
24
+ def run!
25
+ ::FileUtils.mkdir(version) rescue nil
26
+
27
+ @apps = file_paths.map do |path|
28
+ app = App.new(path, version)
29
+ write_plist!(app)
30
+ copy_ipa!(app)
31
+ upload!(app)
32
+ end
33
+
34
+ write_manifest!
35
+ end
36
+
37
+ def write_manifest!
38
+ ::File.join(::Dir.pwd, version, "manifest.txt") do |file|
39
+ apps.each { |app| file << app.install_link }
40
+ end
41
+ end
42
+
43
+ def write_plist!(app)
44
+ log "#{app.name}: writing .plist"
45
+ ::File.open(plist_path(app), 'w') { |file| file << app.plist_xml }
46
+ end
47
+
48
+ def copy_ipa!(app)
49
+ log "#{app.name}: copying .ipa"
50
+ ::FileUtils.cp(app.qualified_path, ipa_path(app))
51
+ end
52
+
53
+ def upload!(app)
54
+ ipa = bucket.files.new({
55
+ key: prefix.join(app.ipa_filename),
56
+ body: ::File.open(ipa_path(app)),
57
+ acl: "public-read"
58
+ })
59
+
60
+ plist = bucket.files.new({
61
+ key: prefix.join(app.plist_filename),
62
+ body: ::File.open(plist_path(app)),
63
+ acl: "public-read"
64
+ })
65
+
66
+ log "#{app.name}: uploading .ipa"
67
+ ipa.save
68
+
69
+ log "#{app.name}: uploading .plist"
70
+ plist.save
71
+ end
72
+
73
+ private
74
+
75
+ def plist_path(app)
76
+ ::File.join(::Dir.pwd, version, app.plist_filename)
77
+ end
78
+
79
+ def ipa_path(app)
80
+ ::File.join(::Dir.pwd, version, app.ipa_filename)
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -1,12 +1,10 @@
1
1
  module Phase
2
2
  module SSH
3
3
  class Backend < ::SSHKit::Backend::Netssh
4
- include ::SSHKit::CommandHelper
5
-
6
- def initialize(*args)
4
+ def initialize(host, options = {})
7
5
  # BUG: Backend::Netssh doesn't assign @pool when subclassed.
8
6
  self.class.pool = ::SSHKit::Backend::ConnectionPool.new
9
- super
7
+ @host = host
10
8
  end
11
9
 
12
10
  def on_remote_host(remote_host, &block)
@@ -14,6 +12,10 @@ module Phase
14
12
  yield
15
13
  end
16
14
 
15
+ def run(&block)
16
+ instance_exec(host, &block)
17
+ end
18
+
17
19
  private
18
20
 
19
21
  def command(*args)
@@ -0,0 +1,44 @@
1
+ module Phase
2
+ module SSH
3
+ class BastionCoordinator
4
+
5
+ def initialize(bastion, destination_hosts)
6
+ @bastion = bastion
7
+ @destination_hosts = destination_hosts
8
+ end
9
+
10
+ def each(options = {}, &block)
11
+ if hosts
12
+ queue = Queue.new
13
+ @destination_hosts.each {|host| queue << hosts }
14
+
15
+ options = default_options.merge(options)
16
+ options[:address_queue] = queue
17
+
18
+ case options[:in]
19
+ when :parallel then ::Phase::SSH::Runners::Parallel
20
+ when :sequence then ::Phase::SSH::Runners::Sequential
21
+ when :groups then ::Phase::SSH::Runners::Group
22
+ else
23
+ raise RuntimeError, "Don't know how to handle run style #{options[:in].inspect}"
24
+ end.new([@bastion] * @destination_hosts.count, options, &block).execute
25
+ else
26
+ Runners::Null.new(hosts, options, &block).execute
27
+ end
28
+ end
29
+
30
+ # def run!(options = {}, &block)
31
+ # backend = Backend.new(@bastion, options)
32
+ #
33
+ # results = @destination_hosts.each do |host|
34
+ # backend.run do
35
+ # on_remote_host(ip) { instance_exec(&block) }
36
+ # end
37
+ # end
38
+ #
39
+ # results.flatten
40
+ # end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module Phase
2
+ module SSH
3
+ module Runners
4
+
5
+ module BastionRunner
6
+ def backend(host, &block)
7
+ backend = ::Phase.config.backend.new(host)
8
+ address = options[:address_queue].pop
9
+
10
+ backend.run do
11
+ on_remote_host(address) { instance_exec(&block) }
12
+ end
13
+ end
14
+ end
15
+
16
+ class Parallel < ::SSHKit::Runner::Parallel
17
+ include BastionRunner
18
+ end
19
+
20
+ class Sequential < ::SSHKit::Runner::Sequential
21
+ include BastionRunner
22
+ end
23
+
24
+ class Null < ::SSHKit::Runner::Null
25
+ include BastionRunner
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,118 @@
1
+ # require "phase/dsl"
2
+ require 'colorize'
3
+
4
+ task deploy: "deploy:all"
5
+
6
+ namespace :deploy do
7
+ task all: [
8
+ :verify_environment,
9
+ :set_version,
10
+ :build_assets,
11
+ :record_deployment
12
+ # :trigger_docker_build
13
+ # :deploy_to_target_servers_in_sequence
14
+ ]
15
+
16
+ task verify_environment: :environment do
17
+ ::Deploy.raise_on_incorrect_branch!
18
+ ::Deploy.raise_on_dirty_index!
19
+ end
20
+
21
+ task set_version: :environment do
22
+ ::Deploy.log "Last release was version #{ ::Deploy.current_version.magenta }"
23
+ next_version_num = ::Deploy.ask "New version number: "
24
+ ::Deploy.write_version(next_version_num)
25
+ end
26
+
27
+ task build_assets: :environment do
28
+ ::Deploy.precompile_assets
29
+ ::Deploy.sync_assets
30
+ end
31
+
32
+ task record_deployment: :environment do
33
+ ::Deploy.stage_changes!
34
+ ::Deploy.commit_deployment!
35
+ end
36
+ end
37
+
38
+
39
+ module Deploy
40
+ class << self
41
+ VERSION_LOCKFILE_PATH = "VERSION"
42
+ VERSION_RBFILE_PATH = "lib/harpoon/version.rb"
43
+
44
+ def ask(str)
45
+ print "[deploy] ".green + str
46
+ STDIN.gets.chomp
47
+ end
48
+
49
+ def commit_deployment!
50
+ system("git commit -m 'Preparing to release v#{ current_version }' -e")
51
+ end
52
+
53
+ def current_version
54
+ ::File.open(VERSION_LOCKFILE_PATH) do |file|
55
+ file.read.chomp
56
+ end
57
+ end
58
+
59
+ def environment
60
+ ARGV[1] || "staging"
61
+ end
62
+
63
+ def fail(str)
64
+ abort("[deploy] error: ".red + str)
65
+ end
66
+
67
+ def log(str)
68
+ puts "[deploy] ".green + str
69
+ end
70
+
71
+ def precompile_assets
72
+ system("RAILS_GROUPS=assets RAILS_ENV=#{ environment } rake assets:precompile")
73
+ end
74
+
75
+ def raise_on_dirty_index!
76
+ unless system('git diff-index --quiet --cached HEAD')
77
+ fail "other changes are already staged. Commit them or 'git reset HEAD' first."
78
+ end
79
+ end
80
+
81
+ def raise_on_incorrect_branch!
82
+ current_branch = `git rev-parse --abbrev-ref HEAD`.chomp
83
+ needed_branch = ::Deploy.environment == "staging" ? "develop" : "master"
84
+
85
+ if current_branch != needed_branch
86
+ fail "your current branch is #{current_branch}. Switch to #{needed_branch}."
87
+ end
88
+ end
89
+
90
+ def stage_changes!
91
+ files = [
92
+ ::Rails.root.join("public", ::Rails.application.config.assets.prefix, "manifest*.json"),
93
+ ::Rails.root.join(::Deploy::VERSION_LOCKFILE_PATH),
94
+ ::Rails.root.join(::Deploy::VERSION_RBFILE_PATH)
95
+ ]
96
+
97
+ system("git add #{ files.join(" ") }")
98
+ end
99
+
100
+ def sync_assets
101
+ system("RAILS_GROUPS=assets RAILS_ENV=#{ environment } rake assets:sync")
102
+ end
103
+
104
+ def write_version(version_num)
105
+ ::File.open(VERSION_LOCKFILE_PATH, 'w') do |file|
106
+ file.write(version_num)
107
+ end
108
+
109
+ ::File.open(VERSION_RBFILE_PATH, 'w') do |file|
110
+ file.write <<-VERSION.strip_heredoc
111
+ module Harpoon
112
+ VERSION = "#{version_num}"
113
+ end
114
+ VERSION
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,15 @@
1
+ module Phase
2
+ module Util
3
+ module Console
4
+
5
+ def log(str)
6
+ puts "[phase]".green + " #{ str }"
7
+ end
8
+
9
+ def fail(str)
10
+ abort "[phase]".red + " #{ str }"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
data/lib/phase/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Phase
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
data/lib/phase.rb CHANGED
@@ -1,20 +1,27 @@
1
- require 'terminal-table'
2
- require 'active_support'
3
- require 'progressbar'
1
+ require 'active_support/all'
2
+ require 'capistrano'
4
3
  require 'colorize'
5
4
  require 'fog'
6
- require 'capistrano'
5
+ require 'progressbar'
6
+ require 'pry'
7
7
  require 'sshkit'
8
+ require 'terminal-table'
8
9
 
9
- require 'dotenv'
10
- ::Dotenv.load if defined?(::Dotenv)
11
10
 
12
11
  require 'phase/adapter'
13
12
  require 'phase/adapters/abstract'
14
13
  require 'phase/adapters/aws'
15
14
 
16
- require 'phase/ssh/backend'
17
- require 'phase/ssh/command'
15
+ require "phase/util/console"
16
+
17
+ require 'phase/kit/ipa/app'
18
+ require 'phase/kit/ipa/enterprise_deployment'
19
+
20
+ require 'phase/kit/ssh/backend'
21
+ # require 'phase/kit/ssh/bastion'
22
+ require 'phase/kit/ssh/bastion_coordinator'
23
+ require 'phase/kit/ssh/command'
24
+ require 'phase/kit/ssh/runners'
18
25
 
19
26
  require 'phase/configuration'
20
27
  require 'phase/version'
@@ -41,5 +48,7 @@ module Phase
41
48
 
42
49
  end
43
50
 
44
- config
51
+ class ResourceNotFoundError < ::StandardError; end
45
52
  end
53
+
54
+ Phase.config.load_phasefile!
data/phase.gemspec CHANGED
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'bundler', '~> 1.6'
33
33
  spec.add_development_dependency 'rake', '~> 10.1'
34
34
  spec.add_development_dependency 'rspec', '~> 3.1'
35
+ spec.add_development_dependency 'pry', '~> 0.10'
35
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piers Mainwaring
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-17 00:00:00.000000000 Z
12
+ date: 2015-04-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: commander
@@ -165,6 +165,20 @@ dependencies:
165
165
  - - "~>"
166
166
  - !ruby/object:Gem::Version
167
167
  version: '3.1'
168
+ - !ruby/object:Gem::Dependency
169
+ name: pry
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '0.10'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - "~>"
180
+ - !ruby/object:Gem::Version
181
+ version: '0.10'
168
182
  description: ''
169
183
  email:
170
184
  - piers@impossibly.org
@@ -196,18 +210,27 @@ files:
196
210
  - lib/phase/cli.rb
197
211
  - lib/phase/cli/all.rb
198
212
  - lib/phase/cli/command.rb
213
+ - lib/phase/cli/deploy.rb
199
214
  - lib/phase/cli/env.rb
215
+ - lib/phase/cli/ipa.rb
200
216
  - lib/phase/cli/keys.rb
201
217
  - lib/phase/cli/logs.rb
202
- - lib/phase/cli/mixins/loggable.rb
203
218
  - lib/phase/cli/mosh.rb
204
219
  - lib/phase/cli/ssh.rb
205
220
  - lib/phase/cli/status.rb
206
221
  - lib/phase/configuration.rb
207
222
  - lib/phase/dsl.rb
208
- - lib/phase/keys/key.rb
209
- - lib/phase/ssh/backend.rb
210
- - lib/phase/ssh/command.rb
223
+ - lib/phase/kit/deploy/build.rb
224
+ - lib/phase/kit/deploy/deployment.rb
225
+ - lib/phase/kit/ipa/app.rb
226
+ - lib/phase/kit/ipa/enterprise_deployment.rb
227
+ - lib/phase/kit/keys/key.rb
228
+ - lib/phase/kit/ssh/backend.rb
229
+ - lib/phase/kit/ssh/bastion_coordinator.rb
230
+ - lib/phase/kit/ssh/command.rb
231
+ - lib/phase/kit/ssh/runners.rb
232
+ - lib/phase/tasks/deploy.rb
233
+ - lib/phase/util/console.rb
211
234
  - lib/phase/version.rb
212
235
  - phase.gemspec
213
236
  - spec/dsl_spec.rb
@@ -1,21 +0,0 @@
1
- module Phase
2
- module CLI
3
- module Mixins
4
- module Loggable
5
-
6
- def log(str)
7
- out = "[phase]".green
8
- out << " #{ str }"
9
- puts out
10
- end
11
-
12
- def fail!(str)
13
- out = "[phase]".red
14
- out << " #{ str }"
15
- abort out
16
- end
17
-
18
- end
19
- end
20
- end
21
- end
File without changes
File without changes