phase 0.0.16.1 → 0.0.17

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: d5ebb4484b885d8dad52f7413fdaf3c50929d193
4
- data.tar.gz: 55d319392ca5d5056f071e05831c951f15a59395
3
+ metadata.gz: 86303d226d273b681f3cee115252b999fdff08f3
4
+ data.tar.gz: 8b6762e471c86eaf776ecaf5fa6ab87346b28d84
5
5
  SHA512:
6
- metadata.gz: 6553814d3f824afe7db88505de68b74dfdc07c8468568ec671512552771684bfb764af74856351dcd5cc02051d703da7d1a7be8a8c3812683b941bed5043a49d
7
- data.tar.gz: 2e1476f1da9b4f3a8088074c049bb9326ceb4323f2f8b7ece9e4e1bf2de07ec06574047d22a2b4444678eb17eaff0b8e97c604ec2e6c347611a4640250f162f4
6
+ metadata.gz: 00a2ff363da264cdcd570c3ca42fe70062efe39d02853c90b4ac9867a2fd6a8faac32d336afccd6f41fe2233169a55a865028a410c0370977b00375e73668fee
7
+ data.tar.gz: b04c21f1298172bef6bff6efa074d3fa7776ecd460c165429ed7040c0e6140e662d10fb58ad70bb685f2f08f645fd8786445017f0eabda087828ff14728cbe3d
@@ -3,7 +3,9 @@ module Phase
3
3
  class Build < Command
4
4
 
5
5
  command :build do |c|
6
- c.syntax = "phase build <version_number>"
6
+ c.syntax = "phase build [-s]"
7
+
8
+ c.option "-s", "--sandbox", String, "Build in sandbox mode: uses current directory's possibly dirty git tree as build context."
7
9
 
8
10
  c.description = <<-EOS.strip_heredoc
9
11
  Builds a new Docker image of the latest committed code on the current branch. Tags the
@@ -11,25 +13,38 @@ module Phase
11
13
  EOS
12
14
 
13
15
  c.action do |args, options|
16
+ options.default(sandbox: false)
14
17
  new(args, options).run
15
18
  end
16
19
  end
17
20
 
18
- attr_reader :version_number
21
+ attr_reader :clean_build, :version_number
19
22
 
20
23
  def initialize(args, options)
21
24
  super
22
-
23
- @version_number = args[0]
24
-
25
- fail "must specify version number" unless version_number
25
+ @clean_build = !options.sandbox
26
26
  end
27
27
 
28
28
  def run
29
- build = ::Phase::Deploy::Build.new(version_number)
29
+ version_number = get_next_version_number
30
+ ::Phase::Deploy::Version.update(version_number) if clean_build
31
+
32
+ build = ::Phase::Deploy::Build.new(version_number, clean: clean_build)
30
33
  build.execute!
31
34
  end
32
35
 
36
+ private
37
+
38
+ def get_next_version_number
39
+ current_version = ::Phase::Deploy::Version.current
40
+
41
+ log "Last release was version #{ current_version.magenta }." if current_version
42
+
43
+ input = ask "New version number:"
44
+ fail "version number is required" if input.blank?
45
+ input
46
+ end
47
+
33
48
  end
34
49
  end
35
50
  end
@@ -13,8 +13,15 @@ module Phase
13
13
  attr_accessor :docker_repository
14
14
 
15
15
 
16
+ # @return [String] the path (relative to Phasefile) to the version lockfile (default "VERSION")
17
+ # @example Sample settings
18
+ # config.deploy.version_lockfile = "lib/myproj/version.lock"
19
+ attr_accessor :version_lockfile
20
+
21
+
16
22
  def initialize
17
23
  @environments = []
24
+ @version_lockfile = "VERSION"
18
25
  end
19
26
 
20
27
  # Adds a new deployment environment.
@@ -4,14 +4,21 @@ module Phase
4
4
  class Build
5
5
  include ::Phase::Util::Shell
6
6
 
7
- attr_reader :version_tag, :build_dir
7
+ attr_reader :build_dir, :clean, :version_tag
8
8
 
9
9
  def initialize(version_tag, options = {})
10
+ @clean = options.fetch(:clean, true)
10
11
  @version_tag = version_tag
11
- @build_dir = ::Pathname.new( options.fetch(:build_dir, "build") )
12
+
13
+ if clean
14
+ @build_dir = ::Pathname.new( options.fetch(:build_dir, "build") )
15
+ else
16
+ @build_dir = ::Pathname.new(".")
17
+ end
12
18
  end
13
19
 
14
20
  def execute!
21
+ check_environment
15
22
  build_image
16
23
  # tag_image
17
24
  push
@@ -20,40 +27,45 @@ module Phase
20
27
  private
21
28
 
22
29
  def build_image
23
- prepare_build
30
+ prepare_clean_build if clean
24
31
 
25
32
  shell("docker build -t #{repo_name}:#{version_tag} #{build_dir}") do |status|
26
- fail "couldn't build Docker image"
33
+ fail "Couldn't build Docker image"
34
+ end
35
+ end
36
+
37
+ def check_environment
38
+ shell("docker ps > /dev/null 2>&1") do |status|
39
+ fail <<-EOS.strip_heredoc
40
+ Docker isn't responding. Is boot2docker running? Try:
41
+ boot2docker start && $(boot2docker shellinit)
42
+ EOS
27
43
  end
28
44
  end
29
45
 
30
46
  def clone_local_git_repo
31
47
  current_branch = `git rev-parse --abbrev-ref HEAD`.strip
32
- shell("git clone --reference $(pwd) --branch #{current_branch} --depth 1 -- file://$(pwd) #{build_dir}") do |status|
33
- fail "couldn't clone local copy of git repository"
48
+ shell("git clone --reference $(pwd) --branch #{current_branch} -- file://$(pwd) #{build_dir}") do |status|
49
+ fail "Couldn't clone local copy of git repository"
34
50
  end
35
51
  end
36
52
 
37
- def prepare_build
53
+ def last_committed_mtime_for_file(file_path)
54
+ rev_hash = `git rev-list HEAD "#{file_path}" | head -n 1`.chomp
55
+ time_str = `git show --pretty=format:%ai --abbrev-commit #{rev_hash} | head -n 1`.chomp
56
+ ::DateTime.parse(time_str).to_time
57
+ end
58
+
59
+ def prepare_clean_build
38
60
  remove_stale_build_dir!
39
61
  clone_local_git_repo
40
62
  set_file_modification_timestamps
41
63
  end
42
64
 
43
- # def tag_image
44
- # shell("docker tag #{repo_name}:#{version_tag} #{repo_name}:latest") do |status|
45
- # fail "couldn't tag Docker image"
46
- # end
47
- # end
48
-
49
65
  def push
50
66
  shell("docker push #{repo_name}:#{version_tag}") do |status|
51
- fail "couldn't push #{repo_name}:#{version_tag}"
67
+ fail "Couldn't push #{repo_name}:#{version_tag}"
52
68
  end
53
-
54
- # shell("docker push #{repo_name}:latest") do |status|
55
- # fail "couldn't push #{repo_name}:latest"
56
- # end
57
69
  end
58
70
 
59
71
  def remove_stale_build_dir!
@@ -65,7 +77,34 @@ module Phase
65
77
  end
66
78
 
67
79
  def set_file_modification_timestamps
68
-
80
+ log "Preparing docker cache..."
81
+
82
+ queue = ::Queue.new
83
+
84
+ ::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")
87
+
88
+ files = `git ls-files`.split
89
+ files.each { |f| queue.push(f) }
90
+
91
+ bar = ::ProgressBar.new("Setting mtimes", files.count)
92
+
93
+ threads = 4.times.map do |idx|
94
+ ::Thread.new do
95
+ begin
96
+ while path = queue.pop(true)
97
+ ::FileUtils.touch(path, mtime: last_committed_mtime_for_file(path))
98
+ bar.inc
99
+ end
100
+ rescue ThreadError
101
+ end
102
+ end
103
+ end
104
+
105
+ threads.each(&:join)
106
+ bar.finish
107
+ end
69
108
  end
70
109
  end
71
110
 
@@ -0,0 +1,29 @@
1
+ module Phase
2
+ module Deploy
3
+
4
+ class Version
5
+ class << self
6
+
7
+ def current
8
+ ::File.read( ::Phase.config.deploy.version_lockfile ).chomp rescue nil
9
+ end
10
+
11
+ def next
12
+ current.to_i + 1
13
+ end
14
+
15
+ def update(new_version)
16
+ write_version(new_version)
17
+ end
18
+
19
+ private
20
+
21
+ def write_version(new_version)
22
+ ::File.open( ::Phase.config.deploy.version_lockfile, 'w' ) { |f| f.write(new_version) }
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -2,10 +2,18 @@ module Phase
2
2
  module Util
3
3
  module Console
4
4
 
5
+ # Prompts user for input.
6
+ def ask(str)
7
+ print "[phase] ".blue.on_cyan + "#{str}".black.on_cyan + " "
8
+ STDIN.gets.chomp
9
+ end
10
+
11
+ # Prints a message.
5
12
  def log(str)
6
13
  puts "[phase]".green + " #{ str }"
7
14
  end
8
15
 
16
+ # Prints a message and then exits.
9
17
  def fail(str)
10
18
  puts
11
19
  abort "[phase]".red + " #{ str }"
data/lib/phase/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Phase
2
- VERSION = "0.0.16.1"
2
+ VERSION = "0.0.17"
3
3
  end
data/lib/phase.rb CHANGED
@@ -7,6 +7,8 @@ require 'progressbar'
7
7
  require 'sshkit'
8
8
  require 'terminal-table'
9
9
 
10
+ require 'pry'
11
+
10
12
 
11
13
  require 'phase/adapter'
12
14
  require 'phase/adapters/abstract'
@@ -17,6 +19,7 @@ require "phase/util/shell"
17
19
 
18
20
  require 'phase/kit/deploy/build'
19
21
  require 'phase/kit/deploy/deployment'
22
+ require 'phase/kit/deploy/version'
20
23
 
21
24
  require 'phase/kit/ipa/app'
22
25
  require 'phase/kit/ipa/enterprise_deployment'
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.16.1
4
+ version: 0.0.17
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-05-29 00:00:00.000000000 Z
12
+ date: 2015-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: commander
@@ -225,6 +225,7 @@ files:
225
225
  - lib/phase/dsl.rb
226
226
  - lib/phase/kit/deploy/build.rb
227
227
  - lib/phase/kit/deploy/deployment.rb
228
+ - lib/phase/kit/deploy/version.rb
228
229
  - lib/phase/kit/ipa/app.rb
229
230
  - lib/phase/kit/ipa/enterprise_deployment.rb
230
231
  - lib/phase/kit/keys/key.rb
@@ -260,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
261
  version: '0'
261
262
  requirements: []
262
263
  rubyforge_project:
263
- rubygems_version: 2.2.2
264
+ rubygems_version: 2.2.3
264
265
  signing_key:
265
266
  specification_version: 4
266
267
  summary: A simple way to manage cloud instances within a multi-subnet network, like