phase 0.0.5 → 0.0.6

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 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