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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 500fa4456778f282bf501ea9d1731a5199f0a2bd
4
- data.tar.gz: 1bfac1ac68d3be949d286dacdec5ef710609c2a8
3
+ metadata.gz: 2d0e11cb6836e13b5e668f722bd179d46b26ee3d
4
+ data.tar.gz: 33e0c0b7778b5e70b25425520f81ee268c02951e
5
5
  SHA512:
6
- metadata.gz: bb354e91c9058f483c8a339ffc9b0f331b152e92a548dd6516c86bd2a56e3caa308dcbad3d287f5cd4ffa2ebb423c438ee48929e8660ab60afb2174810532be2
7
- data.tar.gz: 21d5e9b38e12c614416c75eff044a8c94b49900f913a3e1e2635d6f86c6dcf6f50dd34ca6a3602700e2897a0c8373d967857e78f09048720dccc2118570d4617
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 and
26
- put it in a directory with all of your assets. The manifest file is just a
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. Samus passes all argument values
208
- (the keys from the "arguments" section of the manifest) in as environment
209
- variables with a prefixed underscore. For example, the `rake-task` command
210
- is just:
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
@@ -1,3 +1,5 @@
1
1
  #!/bin/sh
2
2
 
3
+ set -e
4
+ git gc # might as well GC before archiving .git
3
5
  tar cfz $__build_dir/$1 .git $(git ls-files)
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ARGV.each do |file|
3
+ ARGV.map {|f| Dir.glob(f) }.flatten.each do |file|
4
4
  contents = File.read(file)
5
5
  contents = contents.gsub(Regexp.new(ENV['_search']), ENV['_replace'])
6
6
  File.open(file, 'w') {|f| f.write(contents) }
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ npm $_task $*
@@ -0,0 +1,7 @@
1
+ Runs a npm task.
2
+
3
+ Files:
4
+ * An optional list of files to run task on.
5
+
6
+ Arguments:
7
+ * task: the task to execute.
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ samus build -o $__build_dir/$1 $_build_version ${_manifest}
@@ -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.
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ samus publish $1
@@ -0,0 +1,7 @@
1
+ Publishes a Samus release package.
2
+
3
+ Files:
4
+ * The archive name of the generated Samus release package.
5
+
6
+ Arguments:
7
+ * (none)
@@ -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} *"
@@ -4,16 +4,12 @@ module Samus
4
4
  def command_paths; @@command_paths end
5
5
 
6
6
  def list_commands(stage = nil)
7
- stages = {}
8
- command_paths.each do |path|
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
- if $?.to_i != 0
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
@@ -1,3 +1,3 @@
1
1
  module Samus
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
data/samus.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "actions": [
3
3
  {
4
4
  "action": "fs-sedfiles",
5
- "files": ["lib/samus/version.rb"],
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/samus/version.rb"]
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.0.0
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-02-02 00:00:00.000000000 Z
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