harrison 0.5.0 → 0.6.0

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: 438dd20b8530a8b199713be701f928204ffc23f1
4
- data.tar.gz: 73c8b343dd39608a630f6096b22f606014605a6b
3
+ metadata.gz: fbd178c641c35846dfc9376babcf2af16ae15bbe
4
+ data.tar.gz: e27ddc623943e272a38f0fb72f69b1e312a4618e
5
5
  SHA512:
6
- metadata.gz: 0e551411587565663827accb294e2fc3d720af283ecce502a0e401487e1ac17e17f25f04d44f07baab69ae78c2890b383a67c5c38260a3c6f9e55f7e6fd5be51
7
- data.tar.gz: 802fa4f53e5342e40219d7494b8dbe31e00a87388661794746287a38b6141d1547ca1b0d87b4ec9bce93d89dcce6c583c9214044b2ec26dd578205da59c6dc1e
6
+ metadata.gz: ddabbccb099cf66d35df61f1b58589cff24eed24906f238b0785d3a4609cc165d6f91fe3eea1f51cb41c0d92f704d9424cacd4f7b03f641f71c9f4fa47103d47
7
+ data.tar.gz: 81cbf3d1f671f8fcd952756b81baecd9136dd694cdb33a3d3fdc1a6ab12029fa49cfbfd75cdf17d42c156f0bfba5de448dbca7a60e51346bc79e1832a37af384
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ 0.6.0
2
+ -------------------
3
+ - Added ability to package from forks. When packaging from HEAD or a branch,
4
+ harrison will now check to see if that branch is tracking a remote branch.
5
+ If so, it will attempt to package code from that remote. If the branch
6
+ being packaged is not tracking a remote branch, or if what is being packaged
7
+ is not a branch, harrison will look for a remote named "origin" and package
8
+ from there. Lastly, if there is not a remote named "origin", it will package
9
+ from the configured "git_src".
10
+
1
11
  0.5.0
2
12
  -------------------
3
13
  - BREAKING: Bumped net-ssh to 3.2.x which results in Harrison now
data/README.md CHANGED
@@ -119,8 +119,9 @@ Harrison.deploy do |h|
119
119
  end
120
120
  ```
121
121
 
122
- Next, ensure that your SSH key is authorized to log in as the `user` you have specified in
123
- the Harrisonfile for each task. (Or be ready to type the password a lot. :weary:)
122
+ Next, ensure that your SSH key is authorized to log in as the `user` you have
123
+ specified in the Harrisonfile for each task. (Or be ready to type the password
124
+ a lot. :weary:)
124
125
 
125
126
  ### Building a Release
126
127
 
@@ -130,18 +131,25 @@ Use the `harrison package` command:
130
131
  $ harrison package
131
132
  ```
132
133
 
133
- By default this will build and package `HEAD` of your current branch. You may specify another commit to
134
- build using the `--commit` option:
134
+ By default this will build and package `HEAD` of your current branch. You may
135
+ specify another commit to build using the `--commit` option:
135
136
 
136
137
  ```
137
138
  $ harrison package --commit mybranch
138
139
  ```
139
140
 
140
- The `--commit` option understands anything that `git rev-parse` understands. *NOTE: The commit you
141
- reference must be pushed to the repository referenced as `git_src` in the Harrisonfile before
142
- you can build it.*
141
+ The `--commit` option understands anything that `git rev-parse` understands.
142
+ *NOTE: The commit you reference must be pushed to a repository accessible by
143
+ your build server before you can build it.*
143
144
 
144
- The packaged release artifact will, by default, be saved into a local 'pkg' subfolder:
145
+ By default, harrison will automatically detect the correct remote repository to
146
+ attempt to package from by first checking to see if the branch being deployed
147
+ is tracking a specific remote and if not, looking for a remote named "origin"
148
+ to package from. If neither of these is available, it will fall back to the
149
+ git\_src configured in your Harrisonfile.
150
+
151
+ The packaged release artifact will, by default, be saved into a local 'pkg'
152
+ subfolder:
145
153
 
146
154
  ```
147
155
  $ harrison package
@@ -149,8 +157,8 @@ Packaging 5a547d8 for "harrison" on build-server.example.com...
149
157
  Sucessfully packaged 5a547d8 to pkg/20140711170226-5a547d8.tar.gz
150
158
  ```
151
159
 
152
- You can set the destination on the command line with the `--destination` option, or
153
- specify a new default in your Harrisonfile:
160
+ You can set the destination on the command line with the `--destination`
161
+ option, or specify a new default in your Harrisonfile:
154
162
 
155
163
  ```
156
164
  h.destination = '/tmp'
@@ -162,16 +170,18 @@ You can also specify a remote destination:
162
170
  h.destination = 'jesse@artifact-host.example.com:/tmp/artifacts'
163
171
  ```
164
172
 
165
- The username is optional and, if omitted, the build user will be used. *NOTE: Your build server
166
- must have already accepted the SSH host key of the destination server in order to transfer the
167
- artifact.*
173
+ The username is optional and, if omitted, the build user will be used. *NOTE:
174
+ Your build server must have already accepted the SSH host key of the
175
+ destination server in order to transfer the artifact.*
168
176
 
169
- There are some additional options available, run `harrison package --help` to see everything available.
177
+ There are some additional options available, run `harrison package --help` to
178
+ see everything available.
170
179
 
171
180
 
172
181
  ### Deploying a Release
173
182
 
174
- Use the `harrison deploy` command passing the artifact to be deployed as an argument:
183
+ Use the `harrison deploy` command passing the artifact to be deployed as an
184
+ argument:
175
185
 
176
186
  ```
177
187
  $ harrison deploy pkg/20140711170226-5a547d8.tar.gz
@@ -183,10 +193,11 @@ You can also deploy from a remote artifact source:
183
193
  $ harrison deploy jesse@artifact-host.example.com:/tmp/artifacts/20140711170226-5a547d8.tar.gz
184
194
  ```
185
195
 
186
- *NOTE: Each target server must have already accepted the SSH host key of the source server in order to
187
- transfer the artifact.*
196
+ *NOTE: Each target server must have already accepted the SSH host key of the
197
+ source server in order to transfer the artifact.*
188
198
 
189
- By default, the artifact will be deployed to the list of hosts defined in your Harrisonfile.
199
+ By default, the artifact will be deployed to the list of hosts defined in your
200
+ Harrisonfile.
190
201
 
191
202
  You can override the target hosts by passing a `--hosts` option:
192
203
 
@@ -200,7 +211,8 @@ You can also pass an `--env` option to deploy into multi-stage environments:
200
211
  $ harrison deploy pkg/20140711170226-5a547d8.tar.gz --env prod
201
212
  ```
202
213
 
203
- This value can then be tested to alter the default target hosts in your Harrisonfile:
214
+ This value can then be tested to alter the default target hosts in your
215
+ Harrisonfile:
204
216
 
205
217
  ```ruby
206
218
  if h.env =~ /prod/
@@ -210,11 +222,42 @@ else
210
222
  end
211
223
  ```
212
224
 
213
- You can use the `--keep` option (or set it in the deploy section of your Harrisonfile) to specify the total number of
214
- deploys you want to retain on each server after a successful deployment. The default is to keep all previous deploys
215
- around indefinitely.
225
+ The hosts option in your Harrisonfile can also be defined as a block of code
226
+ which will be evaluated in order to calculate a list of hosts to deploy to.
227
+ The code block should evaluate to an array of hostnames, for example:
228
+
229
+ ```ruby
230
+ h.hosts = Proc.new do |h; client, response, instances|
231
+ require 'aws-sdk'
232
+
233
+ AWS.config(region: 'us-west-2')
234
+
235
+ client = AWS.ec2.client
236
+
237
+ response = client.describe_instances(filters: [
238
+ { name: 'tag:Name', values: ["app-server-*.#{h.env}.example.com"] },
239
+ { name: 'instance-state-name', values: ['running'] },
240
+ ])
241
+
242
+ instances = response.data[:reservation_set].flat_map do |r|
243
+ r[:instances_set] && r[:instances_set].collect do |i|
244
+ name_tag = i[:tag_set].find { |tag| tag[:key] == 'Name' }
245
+
246
+ name_tag[:value]
247
+ end
248
+ end
249
+
250
+ instances
251
+ end
252
+ ```
253
+
254
+ You can use the `--keep` option (or set it in the deploy section of your
255
+ Harrisonfile) to specify the total number of deploys you want to retain on each
256
+ server after a successful deployment. The default is to keep all previous
257
+ deploys around indefinitely.
216
258
 
217
- There are some additional options available, run `harrison deploy --help` to see everything available.
259
+ There are some additional options available, run `harrison deploy --help` to
260
+ see everything available.
218
261
 
219
262
 
220
263
  ## Contributing
@@ -33,33 +33,54 @@ module Harrison
33
33
  def run(&block)
34
34
  return super if block_given?
35
35
 
36
+ # Find the URL of the remote in case it differs from git_src.
37
+ remote_url = find_remote(self.commit)
38
+
36
39
  # Resolve commit ref to an actual short SHA.
37
40
  resolve_commit!
38
41
 
39
- puts "Packaging #{commit} for \"#{project}\" on #{host}..."
42
+ puts "Packaging #{commit} from #{remote_url} for \"#{project}\" on #{host}..."
40
43
 
41
44
  # Make sure the folder to save the artifact to locally exists.
42
45
  ensure_destination(destination)
43
46
 
44
- # Fetch/clone git repo on remote host.
45
- remote_exec("if [ -d cached ] ; then cd cached && git fetch origin -p ; else git clone #{git_src} cached ; fi")
46
-
47
- # Make a build folder of the target commit.
48
- remote_exec("rm -rf #{artifact_name(commit)} && cp -a cached #{artifact_name(commit)}")
47
+ # To avoid collisions, we use a version of the full URL as remote name.
48
+ remote_cache_name = remote_url.gsub(/[^a-z0-9_]/i, '_')
49
49
 
50
- # Check out target commit.
51
- remote_exec("cd #{artifact_name(commit)} && git reset --hard #{commit} && git clean -f -d")
50
+ # Fetch/clone git repo on remote host.
51
+ remote_exec <<~ENDCMD
52
+ if [ -d cached ]
53
+ then
54
+ cd cached
55
+ if [ -d .git/refs/remotes/#{remote_cache_name} ]
56
+ then
57
+ git fetch #{remote_cache_name} -p
58
+ else
59
+ git remote add -f #{remote_cache_name} #{remote_url}
60
+ fi
61
+ else
62
+ git clone -o #{remote_cache_name} #{remote_url} cached
63
+ fi
64
+ ENDCMD
65
+
66
+ build_dir = remote_cache_name + '-' + artifact_name(commit)
67
+
68
+ # Clean up any stale build folder of the target remote/commit.
69
+ remote_exec("rm -rf #{build_dir} && mkdir -p #{build_dir}")
70
+
71
+ # Check out target commit into the build_dir.
72
+ remote_exec("cd cached && GIT_WORK_TREE=../#{build_dir} git checkout --detach -f #{commit} && git checkout -f -") # TODO: When git is upgraded: --ignore-other-worktrees
52
73
 
53
74
  # Run user supplied build code in the context of the checked out code.
54
75
  begin
55
- @_remote_context = "#{remote_project_dir}/package/#{artifact_name(commit)}"
76
+ @_remote_context = "#{remote_project_dir}/package/#{build_dir}"
56
77
  super
57
78
  ensure
58
79
  @_remote_context = nil
59
80
  end
60
81
 
61
82
  # Package build folder into tgz.
62
- remote_exec("rm -f #{artifact_name(commit)}.tar.gz && cd #{artifact_name(commit)} && tar #{excludes_for_tar} -czf ../#{artifact_name(commit)}.tar.gz .")
83
+ remote_exec("rm -f #{artifact_name(commit)}.tar.gz && cd #{build_dir} && tar #{excludes_for_tar} -czf ../#{artifact_name(commit)}.tar.gz .")
63
84
 
64
85
  if match = remote_regex.match(destination)
65
86
  # Copy artifact to remote destination.
@@ -73,7 +94,8 @@ module Harrison
73
94
  end
74
95
 
75
96
  if purge
76
- remote_exec("rm -rf #{artifact_name(commit)}")
97
+ remote_exec("rm -rf #{build_dir}")
98
+ remote_exec("rm #{artifact_name(commit)}.tar.gz")
77
99
  end
78
100
 
79
101
  puts "Sucessfully packaged #{commit} to #{destination}/#{artifact_name(commit)}.tar.gz"
@@ -85,6 +107,32 @@ module Harrison
85
107
  "#{remote_dir}/#{project}"
86
108
  end
87
109
 
110
+ def find_remote(ref)
111
+ remote = nil
112
+ remote_url = nil
113
+
114
+ catch :failure do
115
+ # If it's a branch, try to resolve what it's tracking.
116
+ # This will exit non-zero (and throw :failure) if the ref is
117
+ # not a branch.
118
+ remote = exec("git rev-parse --symbolic-full-name #{ref}@{upstream} 2>/dev/null")&.match(/\Arefs\/remotes\/(.+)\/.+\Z/i)&.captures.first
119
+ end
120
+
121
+ # Fallback to 'origin' if not deploying a branch with a tracked
122
+ # upstream.
123
+ remote ||= 'origin'
124
+
125
+ catch :failure do
126
+ # Look for a URL for whatever remote we have. git-config exits
127
+ # non-zero if the requested value doesn't exist.
128
+ remote_url = exec("git config remote.#{remote}.url 2>/dev/null")
129
+ end
130
+
131
+ # If we found a remote_url, return that, otherwise fall back to
132
+ # configured git_src.
133
+ return remote_url || self.git_src
134
+ end
135
+
88
136
  def resolve_commit!
89
137
  self.commit = exec("git rev-parse --short #{self.commit} 2>/dev/null")
90
138
  end
@@ -1,3 +1,3 @@
1
1
  module Harrison
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -4,6 +4,7 @@ describe Harrison::Package do
4
4
  before(:all) do
5
5
  Harrison.class_variable_set(:@@config, Harrison::Config.new)
6
6
  Harrison.config.project = 'test_project'
7
+ Harrison.config.git_src = 'git_src_from_config'
7
8
  end
8
9
 
9
10
  let(:instance) do
@@ -97,6 +98,49 @@ describe Harrison::Package do
97
98
  end
98
99
  end
99
100
 
101
+ describe '#find_remote' do
102
+ before(:each) do
103
+ allow(instance).to receive(:exec).with(/^git config remote.my_remote.url/).and_return('my_remote_url')
104
+ end
105
+
106
+ context 'when deploying a branch that is tracking a remote branch' do
107
+ before(:each) do
108
+ allow(instance).to receive(:exec).with(/^git rev-parse/).and_return('refs/remotes/my_remote/branch')
109
+ end
110
+
111
+ it 'should return url for tracked remote' do
112
+ expect(instance.send(:find_remote, 'HEAD')).to eq 'my_remote_url'
113
+ end
114
+ end
115
+
116
+ context 'when deploying a tree-ish with no remote tracking' do
117
+ before(:each) do
118
+ allow(instance).to receive(:exec).with(/^git rev-parse/).and_throw(:failure)
119
+ end
120
+
121
+ context 'when an \'origin\' remote exists' do
122
+ before(:each) do
123
+ allow(instance).to receive(:exec).with(/^git config remote.origin.url/).and_return('origin_url')
124
+ end
125
+
126
+ it 'should return url for origin' do
127
+ expect(instance.send(:find_remote, 'HEAD')).to eq 'origin_url'
128
+ end
129
+ end
130
+
131
+ context 'when no \'origin\' remote exists' do
132
+ before(:each) do
133
+ allow(instance).to receive(:exec).with(/^git config remote.origin.url/).and_throw(:failure)
134
+ end
135
+
136
+ it 'should return the configured git_src' do
137
+ # git_src is defined globally at the top of this file
138
+ expect(instance.send(:find_remote, 'HEAD')).to eq 'git_src_from_config'
139
+ end
140
+ end
141
+ end
142
+ end
143
+
100
144
  describe '#resolve_commit!' do
101
145
  it 'should resolve commit reference to a short sha using git rev-parse' do
102
146
  instance.commit = 'giant'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harrison
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Scott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-18 00:00:00.000000000 Z
11
+ date: 2016-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trollop