samus 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +173 -8
- data/bin/samus +5 -1
- data/commands/build/archive-git-full +2 -0
- data/commands/build/fs-sedfiles +1 -1
- data/commands/build/npm-task +3 -0
- data/commands/build/npm-task.help.md +7 -0
- data/commands/build/samus-build +3 -0
- data/commands/build/samus-build.help.md +9 -0
- data/commands/publish/samus-publish +3 -0
- data/commands/publish/samus-publish.help.md +7 -0
- data/lib/samus/builder.rb +11 -7
- data/lib/samus/command.rb +25 -13
- data/lib/samus/version.rb +1 -1
- data/samus.json +2 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d0e11cb6836e13b5e668f722bd179d46b26ee3d
|
4
|
+
data.tar.gz: 33e0c0b7778b5e70b25425520f81ee268c02951e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ddd01675f4c353aae8adcd31466dc74bb15d9df3c02e9db9be84f37895dd5672f84c32489b442a55a0afc40c55b5a2e89c61a3f13f7bec0990ac0a9d9fcc6b8
|
7
|
+
data.tar.gz: 11d1f94c34594257b77689ec82a21127921f88382c1d0f91176b4fe19f9758c1e131748f5202eb464bc073bdd4e73f511bb8fb39a23e8d7906d4971ba7f5b966
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Samus
|
1
|
+
# Samus <a href="http://badge.fury.io/rb/samus"><img src="https://badge.fury.io/rb/samus@2x.png" alt="Gem Version" height="18"></a> [![Code Climate](https://codeclimate.com/github/lsegal/samus.png)](https://codeclimate.com/github/lsegal/samus)
|
2
2
|
|
3
3
|
Samus helps you automate the release of Open Source Software. Samus works
|
4
4
|
through a manifest file to describe discrete steps that you typically perform
|
@@ -13,6 +13,14 @@ your code. That's right, Samus has a mechanism to share publishing credentials
|
|
13
13
|
in a fairly secure way, so you can reliably publish releases from almost any
|
14
14
|
machine.
|
15
15
|
|
16
|
+
## Installing
|
17
|
+
|
18
|
+
Samus is a RubyGem and requires Ruby 1.9.x+. Installing is as easy as typing:
|
19
|
+
|
20
|
+
```sh
|
21
|
+
$ gem install samus
|
22
|
+
```
|
23
|
+
|
16
24
|
## Usage
|
17
25
|
|
18
26
|
Samus is driven by a manifest file that describes the steps to perform when
|
@@ -22,9 +30,9 @@ can use it for both, it's your choice.
|
|
22
30
|
### Publishing
|
23
31
|
|
24
32
|
If you can handle building all of your assets on your own, you can use Samus
|
25
|
-
just to publish your code. Create a manifest file called manifest.json
|
26
|
-
put it in a directory with all of your assets. The
|
27
|
-
list of discrete actions like so (minus comments):
|
33
|
+
just to publish your code. Create a manifest file called `manifest.json` (it
|
34
|
+
must be named this way) and put it in a directory with all of your assets. The
|
35
|
+
manifest file is just a list of discrete actions like so (minus comments):
|
28
36
|
|
29
37
|
```js
|
30
38
|
{
|
@@ -204,10 +212,11 @@ The above command creates:
|
|
204
212
|
|
205
213
|
### Commands
|
206
214
|
|
207
|
-
Commands in Samus are just shell scripts
|
208
|
-
|
209
|
-
|
210
|
-
|
215
|
+
Commands in Samus are just shell scripts which execute from the workspace
|
216
|
+
or release directory (unless overridden by the build manifest). Samus passes
|
217
|
+
all argument values (the keys from the "arguments" section of the manifest) in
|
218
|
+
as environment variables with a prefixed underscore. For example, the
|
219
|
+
`rake-task` command is just:
|
211
220
|
|
212
221
|
```sh
|
213
222
|
#!/bin/sh
|
@@ -217,6 +226,58 @@ rake $_task
|
|
217
226
|
|
218
227
|
The `$_task` variable is the "task" argument from the manifest.
|
219
228
|
|
229
|
+
Note that commands must be executable (`chmod +x`) and have proper shebang
|
230
|
+
lines or they will not function.
|
231
|
+
|
232
|
+
#### Stages
|
233
|
+
|
234
|
+
Commands either live in the build/ or publish/ sub-directories under the
|
235
|
+
commands directory depending on whether they are for `samus build` or
|
236
|
+
`samus publish`. These are considered the respective "stages".
|
237
|
+
|
238
|
+
#### Special Variables
|
239
|
+
|
240
|
+
In addition to exposing arguments as underscored environment variables,
|
241
|
+
Samus also exposes a few special variables with double underscore prefixes:
|
242
|
+
|
243
|
+
* `__build_dir` - this variable refers to the temporary directory that the
|
244
|
+
release package is being built inside of. The files inside of this directory,
|
245
|
+
and *only* the files inside of this directory, will be built into the release
|
246
|
+
archive. If you write a build-time command that produces an output file which
|
247
|
+
is part of the release, you should make sure to move it into this directory.
|
248
|
+
* `__restore_file` - the restore file is a newline delimited file containing
|
249
|
+
branches and their original ref. All branches listed in this file will be
|
250
|
+
restored to the respective ref at the end of `samus build` regardless of
|
251
|
+
success status. If you make destructive modifications to existing branches
|
252
|
+
in the workspace repository, you should add the original ref for the branch
|
253
|
+
to this file.
|
254
|
+
* `__creds_*` - provides key, secret, and other values loaded from credentials.
|
255
|
+
See Credentials section for more information on how these are set.
|
256
|
+
|
257
|
+
#### Help Files
|
258
|
+
|
259
|
+
In order to integrate with `samus show-cmd <stage> <command>` syntax, your
|
260
|
+
command should include a file named `your-command.help.md` in the same directory
|
261
|
+
as the command script itself. These files are Markdown-formatted files and
|
262
|
+
should follow the same structure of the built-in command help files:
|
263
|
+
|
264
|
+
```
|
265
|
+
Short description of command.
|
266
|
+
|
267
|
+
* Files:
|
268
|
+
* Description of what the command line arguments are
|
269
|
+
|
270
|
+
* Arguments:
|
271
|
+
* argname: Documentation for argument
|
272
|
+
```
|
273
|
+
|
274
|
+
Notes:
|
275
|
+
|
276
|
+
* The first line of the help file is used as the summary in the `show-cmd`
|
277
|
+
listing.
|
278
|
+
* Never omit a section. If a command has no files or arguments, use "(none)"
|
279
|
+
as the list item text.
|
280
|
+
|
220
281
|
### Credentials
|
221
282
|
|
222
283
|
Custom credentials are just flat files or executables in the `credentials/`
|
@@ -244,6 +305,110 @@ These values are read in by Samus and get exposed as `$__creds_key` and
|
|
244
305
|
metadata as well, which would be included as `$__creds_name` (for the
|
245
306
|
line "NAME: value").
|
246
307
|
|
308
|
+
## Manifest File Format
|
309
|
+
|
310
|
+
The following section defines the manifest formats for the samus.json build
|
311
|
+
manifest as well as the manifest.json stored in release packages.
|
312
|
+
|
313
|
+
### Base Format
|
314
|
+
|
315
|
+
The base format is defined as follows:
|
316
|
+
|
317
|
+
```js
|
318
|
+
{
|
319
|
+
"actions": [
|
320
|
+
{
|
321
|
+
"action": "COMMAND_NAME", // [required] command name to execute
|
322
|
+
"files": ["file1", ...], // optional list of files
|
323
|
+
"arguments": { // optional map of arguments to pass to cmd
|
324
|
+
"key": "value", // each key is passed in as _key in ENV
|
325
|
+
// ... (optional) more keys ...
|
326
|
+
},
|
327
|
+
"pwd": "path" // optional path to execute command from
|
328
|
+
"credentials": "KEY", // optional credentials to load for cmd
|
329
|
+
},
|
330
|
+
// ... (optional) more action items ...
|
331
|
+
]
|
332
|
+
}
|
333
|
+
```
|
334
|
+
|
335
|
+
All manifests include a list of "actions", known individually as action items.
|
336
|
+
Each action item has a single required property, "action", which is the command
|
337
|
+
to execute for the action (found in `samus show-cmd`). An optional list of
|
338
|
+
files are passed into the command as command line arguments, and the "arguments"
|
339
|
+
property is a map of keys to values passed in as environment variables with a
|
340
|
+
"\_" prefix (key "foo" is set as environment variable "_foo"). Optional
|
341
|
+
credentials are loaded from the credentials directory.
|
342
|
+
|
343
|
+
### Build Manifest Format
|
344
|
+
|
345
|
+
The build manifest format is similar to the above but allows for two extra keys
|
346
|
+
in each action item called "publish" and "condition".
|
347
|
+
|
348
|
+
#### "publish" Property
|
349
|
+
|
350
|
+
The "publish" property should contain the action item that is added to the
|
351
|
+
final manifest.json built into the release package if the action item is
|
352
|
+
evaluated (condition matches and command successfully executes). If a "files"
|
353
|
+
property is set on the parent action item, that property is copied into the
|
354
|
+
publish action by default, but it can be overridden.
|
355
|
+
|
356
|
+
Here is an example build manifest showing the added use of the "publish"
|
357
|
+
property:
|
358
|
+
|
359
|
+
```js
|
360
|
+
{
|
361
|
+
"actions": [
|
362
|
+
{
|
363
|
+
"action": "readme-update",
|
364
|
+
"files": ["README.txt"],
|
365
|
+
"publish": {
|
366
|
+
"action": "readme-publish"
|
367
|
+
"arguments": {
|
368
|
+
"host": "www.mywebsite.com"
|
369
|
+
},
|
370
|
+
"credentials": "www.mywebsite.com"
|
371
|
+
}
|
372
|
+
},
|
373
|
+
{
|
374
|
+
"action": "readme-build",
|
375
|
+
"files": ["README.txt"],
|
376
|
+
"publish": {
|
377
|
+
"action": "readme-publish"
|
378
|
+
"arguments": {
|
379
|
+
"files": ["README.html"], // override files property
|
380
|
+
"host": "www.mywebsite.com"
|
381
|
+
},
|
382
|
+
"credentials": "www.mywebsite.com"
|
383
|
+
}
|
384
|
+
}
|
385
|
+
]
|
386
|
+
|
387
|
+
}
|
388
|
+
```
|
389
|
+
|
390
|
+
#### "condition" Property
|
391
|
+
|
392
|
+
The "condition" property is a Ruby expression that is evaluated for truthiness
|
393
|
+
to decide if the action item should be evaluated or skipped. A common use for
|
394
|
+
this is to take action based on the version (see "$version" variable section
|
395
|
+
below). The following example runs an action item only for version 2.0+ of a
|
396
|
+
release:
|
397
|
+
|
398
|
+
```js
|
399
|
+
{
|
400
|
+
"action": "rake-task",
|
401
|
+
"arguments": { "task": "assets:package" },
|
402
|
+
"condition": "'$version' > '2.0'"
|
403
|
+
}
|
404
|
+
```
|
405
|
+
|
406
|
+
#### "$version" Variable
|
407
|
+
|
408
|
+
A special variable "$version" is interpolated when loading the build manifest.
|
409
|
+
This variable can appear anywhere in the JSON document, and is interpolated
|
410
|
+
before any actions or conditions are evaluated.
|
411
|
+
|
247
412
|
## Contributing & TODO
|
248
413
|
|
249
414
|
Please help by contributing commands that Samus can use to build or publish
|
data/bin/samus
CHANGED
@@ -40,6 +40,7 @@ end
|
|
40
40
|
|
41
41
|
dry_run = false
|
42
42
|
zip_release = true
|
43
|
+
outfile = nil
|
43
44
|
opts = OptionParser.new do |opts|
|
44
45
|
opts.banner = "Usage: samus publish [options] <directory> [directory ...]\n"
|
45
46
|
opts.banner += " samus build [options] <version> [build.json]\n"
|
@@ -54,6 +55,9 @@ opts = OptionParser.new do |opts|
|
|
54
55
|
opts.on("--[no-]zip", "Zip release directory") do |zip|
|
55
56
|
zip_release = zip
|
56
57
|
end
|
58
|
+
opts.on("-o FILE", "--output", "The file (no extension) to generate") do |file|
|
59
|
+
outfile = file
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
59
63
|
opts.parse!
|
@@ -79,7 +83,7 @@ elsif command == Samus::Builder
|
|
79
83
|
$VERSION = $VERSION.sub(/^v/, '')
|
80
84
|
|
81
85
|
(ARGV.empty? ? ['samus.json'] : ARGV).each do |file|
|
82
|
-
command.new(file).build(dry_run, zip_release)
|
86
|
+
command.new(file).build(dry_run, zip_release, outfile)
|
83
87
|
end
|
84
88
|
else
|
85
89
|
puts opts
|
data/commands/build/fs-sedfiles
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
Builds a separate Samus-backed repository as part of this Samus build.
|
2
|
+
|
3
|
+
Files:
|
4
|
+
* The archive name of the generated Samus release package.
|
5
|
+
|
6
|
+
Arguments:
|
7
|
+
* build_version: the version of the package to build.
|
8
|
+
* manifest: (optional) the name of the manifest to use when building the
|
9
|
+
manifest.
|
data/lib/samus/builder.rb
CHANGED
@@ -16,12 +16,16 @@ module Samus
|
|
16
16
|
@manifest = {}
|
17
17
|
end
|
18
18
|
|
19
|
-
def build(dry_run = false, zip_release = true)
|
19
|
+
def build(dry_run = false, zip_release = true, outfile = nil)
|
20
20
|
orig_pwd = Dir.pwd
|
21
21
|
manifest = {'version' => $VERSION, 'actions' => []}
|
22
22
|
build_branch = "samus-release/v#{$VERSION}"
|
23
23
|
orig_branch = `git symbolic-ref -q --short HEAD`.chomp
|
24
24
|
|
25
|
+
if `git diff --shortstat 2> /dev/null | tail -n1` != ""
|
26
|
+
Samus.error "Repository is dirty, it is too dangerous to continue."
|
27
|
+
end
|
28
|
+
|
25
29
|
system "git checkout -qb #{build_branch} 2>/dev/null"
|
26
30
|
remove_restore_file
|
27
31
|
|
@@ -41,14 +45,14 @@ module Samus
|
|
41
45
|
|
42
46
|
Dir.chdir(build_dir) do
|
43
47
|
generate_manifest(manifest)
|
44
|
-
generate_release(orig_pwd, zip_release)
|
48
|
+
generate_release(orig_pwd, zip_release, outfile)
|
45
49
|
end unless dry_run
|
46
50
|
end
|
47
51
|
|
48
52
|
ensure
|
49
53
|
restore_git_repo
|
50
|
-
system "git checkout -q #{orig_branch}"
|
51
|
-
system "git branch -qD #{build_branch}"
|
54
|
+
system "git checkout -q #{orig_branch} 2>/dev/null"
|
55
|
+
system "git branch -qD #{build_branch} 2>/dev/null"
|
52
56
|
end
|
53
57
|
|
54
58
|
private
|
@@ -59,9 +63,9 @@ module Samus
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
def generate_release(orig_pwd, zip_release = true)
|
63
|
-
file = build_manifest['output'] || "release-v#{$VERSION}"
|
64
|
-
file = File.join(orig_pwd, file)
|
66
|
+
def generate_release(orig_pwd, zip_release = true, outfile = nil)
|
67
|
+
file = outfile || build_manifest['output'] || "release-v#{$VERSION}"
|
68
|
+
file = File.join(orig_pwd, file) unless file[0] == '/'
|
65
69
|
if zip_release
|
66
70
|
file += '.tar.gz'
|
67
71
|
system "tar cfz #{file} *"
|
data/lib/samus/command.rb
CHANGED
@@ -4,16 +4,12 @@ module Samus
|
|
4
4
|
def command_paths; @@command_paths end
|
5
5
|
|
6
6
|
def list_commands(stage = nil)
|
7
|
-
|
8
|
-
|
9
|
-
Dir.glob(File.join(path, '*', '*')).each do |dir|
|
10
|
-
type, name = *dir.split(File::SEPARATOR)[-2,2]
|
11
|
-
next if name =~ /\.md$/
|
12
|
-
next if stage && stage != type
|
13
|
-
(stages[type] ||= []).push(new(type, name))
|
14
|
-
end
|
15
|
-
end
|
7
|
+
display_commands(collect_commands(stage))
|
8
|
+
end
|
16
9
|
|
10
|
+
private
|
11
|
+
|
12
|
+
def display_commands(stages)
|
17
13
|
puts "Commands:"
|
18
14
|
puts ""
|
19
15
|
stages.each do |type, commands|
|
@@ -25,6 +21,19 @@ module Samus
|
|
25
21
|
puts ""
|
26
22
|
end
|
27
23
|
end
|
24
|
+
|
25
|
+
def collect_commands(stage)
|
26
|
+
stages = {}
|
27
|
+
command_paths.each do |path|
|
28
|
+
Dir.glob(File.join(path, '*', '*')).each do |dir|
|
29
|
+
type, name = *dir.split(File::SEPARATOR)[-2,2]
|
30
|
+
next if name =~ /\.md$/
|
31
|
+
next if stage && stage != type
|
32
|
+
(stages[type] ||= []).push(new(type, name))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
stages
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
@@command_paths = [File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'commands'))]
|
@@ -66,10 +75,7 @@ module Samus
|
|
66
75
|
exec_in_dir(pwd) do
|
67
76
|
system(env, @full_path + " " + (arguments ? arguments.join(" ") : ""))
|
68
77
|
end
|
69
|
-
|
70
|
-
puts "[E] Last command failed with #{$?}#{allow_fail ? ' but allowFail=true' : ', exiting'}."
|
71
|
-
exit($?.to_i) unless allow_fail
|
72
|
-
end
|
78
|
+
report_error($?, allow_fail)
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
@@ -79,6 +85,12 @@ module Samus
|
|
79
85
|
|
80
86
|
private
|
81
87
|
|
88
|
+
def report_error(exit_code, allow_fail)
|
89
|
+
return if exit_code.to_i == 0
|
90
|
+
puts "[E] Last command failed with #{exit_code}#{allow_fail ? ' but allowFail=true' : ', exiting'}."
|
91
|
+
exit(exit_code.to_i) unless allow_fail
|
92
|
+
end
|
93
|
+
|
82
94
|
def exec_in_dir(dir, &block)
|
83
95
|
dir ? Dir.chdir(dir, &block) : yield
|
84
96
|
end
|
data/lib/samus/version.rb
CHANGED
data/samus.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"actions": [
|
3
3
|
{
|
4
4
|
"action": "fs-sedfiles",
|
5
|
-
"files": ["lib
|
5
|
+
"files": ["lib/*/version.rb"],
|
6
6
|
"arguments": {
|
7
7
|
"search": "VERSION = ['\"](.+?)['\"]",
|
8
8
|
"replace": "VERSION = '$version'"
|
@@ -10,7 +10,7 @@
|
|
10
10
|
},
|
11
11
|
{
|
12
12
|
"action": "git-commit",
|
13
|
-
"files": ["lib
|
13
|
+
"files": ["lib/*/version.rb"]
|
14
14
|
},
|
15
15
|
{
|
16
16
|
"action": "git-merge",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: samus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loren Segal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: lsegal@soen.ca
|
@@ -42,10 +42,14 @@ files:
|
|
42
42
|
- commands/build/git-commit.help.md
|
43
43
|
- commands/build/git-merge
|
44
44
|
- commands/build/git-merge.help.md
|
45
|
+
- commands/build/npm-task
|
46
|
+
- commands/build/npm-task.help.md
|
45
47
|
- commands/build/npm-test
|
46
48
|
- commands/build/npm-test.help.md
|
47
49
|
- commands/build/rake-task
|
48
50
|
- commands/build/rake-task.help.md
|
51
|
+
- commands/build/samus-build
|
52
|
+
- commands/build/samus-build.help.md
|
49
53
|
- commands/publish/cf-invalidate
|
50
54
|
- commands/publish/cf-invalidate.help.md
|
51
55
|
- commands/publish/gem-push
|
@@ -56,6 +60,8 @@ files:
|
|
56
60
|
- commands/publish/npm-publish.help.md
|
57
61
|
- commands/publish/s3-put
|
58
62
|
- commands/publish/s3-put.help.md
|
63
|
+
- commands/publish/samus-publish
|
64
|
+
- commands/publish/samus-publish.help.md
|
59
65
|
- lib/samus.rb
|
60
66
|
- lib/samus/action.rb
|
61
67
|
- lib/samus/build_action.rb
|