phase 0.0.17 → 1.0.0.rc1

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: 86303d226d273b681f3cee115252b999fdff08f3
4
- data.tar.gz: 8b6762e471c86eaf776ecaf5fa6ab87346b28d84
3
+ metadata.gz: 9418e0cabac33009818c8d089c896b5b4cb81004
4
+ data.tar.gz: b7346fdc18bcad141314d0e96247e6bb9e3aaf55
5
5
  SHA512:
6
- metadata.gz: 00a2ff363da264cdcd570c3ca42fe70062efe39d02853c90b4ac9867a2fd6a8faac32d336afccd6f41fe2233169a55a865028a410c0370977b00375e73668fee
7
- data.tar.gz: b04c21f1298172bef6bff6efa074d3fa7776ecd460c165429ed7040c0e6140e662d10fb58ad70bb685f2f08f645fd8786445017f0eabda087828ff14728cbe3d
6
+ metadata.gz: 94f9716929b4f0b402104f6c9012300664dde3c1e35df93bd914aa84ed4fbd236f59534f062648a56bc768e745369ea0d3ea0fefcd8dd6aeaaa8ee7eb1860026
7
+ data.tar.gz: 15248f3be2d0e843db4f9778421715204d965af8d1822113f104aea05f081c7304808f96e0d95a6d9221084aeaba267baf8a885064ba8d592b0fa89726da372f
@@ -27,9 +27,8 @@ module Phase
27
27
 
28
28
  def run
29
29
  version_number = get_next_version_number
30
- ::Phase::Deploy::Version.update(version_number) if clean_build
31
30
 
32
- build = ::Phase::Deploy::Build.new(version_number, clean: clean_build)
31
+ build = ::Phase::Deploy::Build.new(version_number, clean_build: clean_build)
33
32
  build.execute!
34
33
  end
35
34
 
@@ -41,7 +40,7 @@ module Phase
41
40
  log "Last release was version #{ current_version.magenta }." if current_version
42
41
 
43
42
  input = ask "New version number:"
44
- fail "version number is required" if input.blank?
43
+ fail "Version number is required" if input.blank?
45
44
  input
46
45
  end
47
46
 
data/lib/phase/cli/ssh.rb CHANGED
@@ -2,7 +2,7 @@ module Phase
2
2
  module CLI
3
3
  class SSH < Command
4
4
  command :ssh do |c|
5
- c.syntax = "phase ssh [-i instance_id] [-n instance_name] [-r instance_role] [-u user] [-c conn_str] [username@instance_name|instance_id]"
5
+ c.syntax = "phase ssh [-i instance_id] [-n instance_name] [-r instance_role] [-u user] [-c conn_str] [username@instance_name|instance_id] [command...]"
6
6
 
7
7
  c.option "-i", "--id instance_id", String, "Connects to the instance with this ID."
8
8
  c.option "-n", "--name instance_name", String, "Connects to the instance with this 'Name' tag."
@@ -21,8 +21,15 @@ module Phase
21
21
 
22
22
  def run
23
23
  parse_connection_string
24
- log "connecting to instance #{ instance.resource.id }..."
25
- exec "#{ options.conn } #{ username }@#{ instance.resource.dns_name }"
24
+ ssh_command = args.last if args.count > 1
25
+
26
+ if ssh_command
27
+ log "running on instance #{ instance.resource.id }: `#{ ssh_command }'"
28
+ exec "#{ options.conn } #{ username }@#{ instance.resource.dns_name } #{ ssh_command }"
29
+ else
30
+ log "connecting to instance #{ instance.resource.id }..."
31
+ exec "#{ options.conn } #{ username }@#{ instance.resource.dns_name }"
32
+ end
26
33
  end
27
34
 
28
35
  private
@@ -19,6 +19,12 @@ module Phase
19
19
  attr_accessor :version_lockfile
20
20
 
21
21
 
22
+ # @return [String] the cloud storage bucket ("directory") for storing compiled assets
23
+ # @example Sample settings
24
+ # config.deploy.docker_repository = "static-assets"
25
+ attr_accessor :asset_bucket
26
+
27
+
22
28
  def initialize
23
29
  @environments = []
24
30
  @version_lockfile = "VERSION"
@@ -4,13 +4,13 @@ module Phase
4
4
  class Build
5
5
  include ::Phase::Util::Shell
6
6
 
7
- attr_reader :build_dir, :clean, :version_tag
7
+ attr_reader :build_dir, :clean_build, :version_tag
8
8
 
9
9
  def initialize(version_tag, options = {})
10
- @clean = options.fetch(:clean, true)
10
+ @clean_build = options.fetch(:clean_build, true)
11
11
  @version_tag = version_tag
12
12
 
13
- if clean
13
+ if clean_build
14
14
  @build_dir = ::Pathname.new( options.fetch(:build_dir, "build") )
15
15
  else
16
16
  @build_dir = ::Pathname.new(".")
@@ -18,29 +18,45 @@ module Phase
18
18
  end
19
19
 
20
20
  def execute!
21
- check_environment
21
+ prepare_environment
22
+ build_assets
23
+ commit_new_version!
22
24
  build_image
23
- # tag_image
24
25
  push
25
26
  end
26
27
 
27
28
  private
28
29
 
30
+ def build_assets
31
+ precompile_assets
32
+ sync_assets
33
+ end
34
+
29
35
  def build_image
30
- prepare_clean_build if clean
36
+ prepare_clean_build if clean_build
31
37
 
32
- shell("docker build -t #{repo_name}:#{version_tag} #{build_dir}") do |status|
38
+ shell("docker build -t #{docker_repo}:#{version_tag} #{build_dir}") do |status|
33
39
  fail "Couldn't build Docker image"
34
40
  end
35
41
  end
36
42
 
37
- def check_environment
43
+ def commit_new_version!
44
+ ::Phase::Deploy::Version.update(version_tag)
45
+ shell("git add -f public/assets/*manifest* #{::Phase.config.deploy.version_lockfile}", allow_failure: true)
46
+ shell("git commit -m 'Built v#{version_tag}'", allow_failure: true)
47
+ end
48
+
49
+ def prepare_environment
50
+ raise_on_dirty_index!
51
+
38
52
  shell("docker ps > /dev/null 2>&1") do |status|
39
53
  fail <<-EOS.strip_heredoc
40
54
  Docker isn't responding. Is boot2docker running? Try:
41
55
  boot2docker start && $(boot2docker shellinit)
42
56
  EOS
43
57
  end
58
+
59
+ pull_latest_build
44
60
  end
45
61
 
46
62
  def clone_local_git_repo
@@ -50,40 +66,62 @@ module Phase
50
66
  end
51
67
  end
52
68
 
69
+ def docker_repo
70
+ ::Phase.config.deploy.docker_repository
71
+ end
72
+
53
73
  def last_committed_mtime_for_file(file_path)
54
74
  rev_hash = `git rev-list HEAD "#{file_path}" | head -n 1`.chomp
55
75
  time_str = `git show --pretty=format:%ai --abbrev-commit #{rev_hash} | head -n 1`.chomp
56
76
  ::DateTime.parse(time_str).to_time
57
77
  end
58
78
 
79
+ # FIXME: This approach isn't ideal because it compiles assets in the *working* git
80
+ # directory rather than building in a clean, committed environment. This could lead
81
+ # to errors in the compiled assets.
82
+ def precompile_assets
83
+ shell("RAILS_GROUPS=assets rake assets:precompile") do |status|
84
+ fail "Couldn't precompile assets"
85
+ end
86
+ end
87
+
59
88
  def prepare_clean_build
60
89
  remove_stale_build_dir!
61
90
  clone_local_git_repo
62
91
  set_file_modification_timestamps
63
92
  end
64
93
 
94
+ # This needs to run *before* the version gets updated so we know which version
95
+ # number to pull from the registry.
96
+ def pull_latest_build
97
+ shell("docker pull #{docker_repo}:#{::Phase::Deploy::Version.current}")
98
+ end
99
+
65
100
  def push
66
- shell("docker push #{repo_name}:#{version_tag}") do |status|
67
- fail "Couldn't push #{repo_name}:#{version_tag}"
101
+ shell("docker push #{docker_repo}:#{version_tag}") do |status|
102
+ fail "Couldn't push #{docker_repo}:#{version_tag}"
68
103
  end
69
104
  end
70
105
 
71
- def remove_stale_build_dir!
72
- ::FileUtils.rm_rf(build_dir)
106
+ def raise_on_dirty_index!
107
+ shell('git diff-index --quiet --cached HEAD') do |status|
108
+ fail "Other changes are already staged. Commit or stash them first"
109
+ end
73
110
  end
74
111
 
75
- def repo_name
76
- ::Phase.config.deploy.docker_repository
112
+ def remove_stale_build_dir!
113
+ ::FileUtils.rm_rf(build_dir)
77
114
  end
78
115
 
79
116
  def set_file_modification_timestamps
80
- log "Preparing docker cache..."
117
+ log("Preparing docker cache...")
81
118
 
119
+ # Threadsafe queue for multiple threads to pull from
82
120
  queue = ::Queue.new
83
121
 
84
122
  ::FileUtils.cd(build_dir) do
85
- # Sets consistent mtime on directories because docker cares about that
86
- system("find . -type d | xargs touch -t 7805200000")
123
+ # Sets consistent mtime on directories because docker cares about that too
124
+ shell("find . -type d | xargs touch -t 7805200000")
87
125
 
88
126
  files = `git ls-files`.split
89
127
  files.each { |f| queue.push(f) }
@@ -106,6 +144,15 @@ module Phase
106
144
  bar.finish
107
145
  end
108
146
  end
147
+
148
+ def sync_assets
149
+ bucket = ::Phase.config.deploy.asset_bucket
150
+ return log("Set `deploy.asset_bucket` in Phasefile to enable asset syncing") if bucket.blank?
151
+
152
+ shell("RAILS_GROUPS=assets FOG_DIRECTORY=#{bucket} rake assets:sync") do |status|
153
+ fail "Couldn't sync assets to The Clouds"
154
+ end
155
+ end
109
156
  end
110
157
 
111
158
  end
@@ -15,7 +15,6 @@ module Phase
15
15
 
16
16
  # Prints a message and then exits.
17
17
  def fail(str)
18
- puts
19
18
  abort "[phase]".red + " #{ str }"
20
19
  end
21
20
 
@@ -4,10 +4,17 @@ module Phase
4
4
  include Console
5
5
 
6
6
  def shell(*args)
7
+ options = args.extract_options!
8
+ options.reverse_merge({
9
+ allow_failure: false
10
+ })
11
+
7
12
  log "running: #{args.join(' ')}"
8
- status = !!system(*args)
9
- yield $? unless status
10
- return status
13
+ succeeded = !!system(*args) || options[:allow_failure]
14
+
15
+ yield $? unless succeeded
16
+
17
+ succeeded
11
18
  end
12
19
 
13
20
  end
data/lib/phase/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Phase
2
- VERSION = "0.0.17"
2
+ VERSION = "1.0.0.rc1"
3
3
  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.17
4
+ version: 1.0.0.rc1
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: 2015-06-12 00:00:00.000000000 Z
12
+ date: 2015-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: commander
@@ -256,9 +256,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
256
  version: '2.0'
257
257
  required_rubygems_version: !ruby/object:Gem::Requirement
258
258
  requirements:
259
- - - ">="
259
+ - - ">"
260
260
  - !ruby/object:Gem::Version
261
- version: '0'
261
+ version: 1.3.1
262
262
  requirements: []
263
263
  rubyforge_project:
264
264
  rubygems_version: 2.2.3