harrison 0.5.0 → 0.6.0

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