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 +4 -4
- data/CHANGELOG +10 -0
- data/README.md +66 -23
- data/lib/harrison/package.rb +59 -11
- data/lib/harrison/version.rb +1 -1
- data/spec/unit/harrison/package_spec.rb +44 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbd178c641c35846dfc9376babcf2af16ae15bbe
|
4
|
+
data.tar.gz: e27ddc623943e272a38f0fb72f69b1e312a4618e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
123
|
-
the Harrisonfile for each task. (Or be ready to type the password
|
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
|
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.
|
141
|
-
reference must be pushed to
|
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
|
-
|
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`
|
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:
|
166
|
-
must have already accepted the SSH host key of 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
|
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
|
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
|
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
|
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
|
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
|
-
|
214
|
-
|
215
|
-
|
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
|
259
|
+
There are some additional options available, run `harrison deploy --help` to
|
260
|
+
see everything available.
|
218
261
|
|
219
262
|
|
220
263
|
## Contributing
|
data/lib/harrison/package.rb
CHANGED
@@ -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
|
-
#
|
45
|
-
|
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
|
-
#
|
51
|
-
remote_exec
|
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/#{
|
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 #{
|
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 #{
|
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
|
data/lib/harrison/version.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2016-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trollop
|