samus 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +255 -0
  4. data/bin/samus +87 -0
  5. data/commands/build/archive-git-full +3 -0
  6. data/commands/build/archive-git-full.help.md +7 -0
  7. data/commands/build/archive-tgz +3 -0
  8. data/commands/build/archive-tgz.help.md +7 -0
  9. data/commands/build/archive-zip +3 -0
  10. data/commands/build/archive-zip.help.md +7 -0
  11. data/commands/build/fs-copy +3 -0
  12. data/commands/build/fs-copy.help.md +8 -0
  13. data/commands/build/fs-mkdir +3 -0
  14. data/commands/build/fs-mkdir.help.md +7 -0
  15. data/commands/build/fs-rmrf +3 -0
  16. data/commands/build/fs-rmrf.help.md +7 -0
  17. data/commands/build/fs-sedfiles +7 -0
  18. data/commands/build/fs-sedfiles.help.md +8 -0
  19. data/commands/build/gem-build +5 -0
  20. data/commands/build/gem-build.help.md +7 -0
  21. data/commands/build/git-archive +3 -0
  22. data/commands/build/git-archive.help.md +8 -0
  23. data/commands/build/git-commit +7 -0
  24. data/commands/build/git-commit.help.md +8 -0
  25. data/commands/build/git-merge +9 -0
  26. data/commands/build/git-merge.help.md +8 -0
  27. data/commands/build/npm-test +3 -0
  28. data/commands/build/npm-test.help.md +7 -0
  29. data/commands/build/rake-task +3 -0
  30. data/commands/build/rake-task.help.md +7 -0
  31. data/commands/publish/cf-invalidate +16 -0
  32. data/commands/publish/cf-invalidate.help.md +8 -0
  33. data/commands/publish/gem-push +6 -0
  34. data/commands/publish/gem-push.help.md +7 -0
  35. data/commands/publish/git-push +15 -0
  36. data/commands/publish/git-push.help.md +8 -0
  37. data/commands/publish/npm-publish +3 -0
  38. data/commands/publish/npm-publish.help.md +7 -0
  39. data/commands/publish/s3-put +13 -0
  40. data/commands/publish/s3-put.help.md +10 -0
  41. data/lib/samus.rb +37 -0
  42. data/lib/samus/action.rb +60 -0
  43. data/lib/samus/build_action.rb +46 -0
  44. data/lib/samus/builder.rb +101 -0
  45. data/lib/samus/command.rb +99 -0
  46. data/lib/samus/credentials.rb +48 -0
  47. data/lib/samus/publish_action.rb +7 -0
  48. data/lib/samus/publisher.rb +38 -0
  49. data/lib/samus/version.rb +3 -0
  50. data/samus.gemspec +13 -0
  51. data/samus.json +44 -0
  52. metadata +95 -0
@@ -0,0 +1,7 @@
1
+ Removes a set of files from the build directory.
2
+
3
+ Files:
4
+ * A list of files relative to the build directory to delete.
5
+
6
+ Arguments:
7
+ * (none)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ARGV.each do |file|
4
+ contents = File.read(file)
5
+ contents = contents.gsub(Regexp.new(ENV['_search']), ENV['_replace'])
6
+ File.open(file, 'w') {|f| f.write(contents) }
7
+ end
@@ -0,0 +1,8 @@
1
+ Replaces text in a list of files in the working copy.
2
+
3
+ Files:
4
+ * A list of files to perform text replacement on.
5
+
6
+ Arguments:
7
+ * search: a regular expression to search for.
8
+ * replace: the text to replace.
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ gem build $1
5
+ mv ${1%.gemspec}-$_version.gem $__build_dir
@@ -0,0 +1,7 @@
1
+ Builds a RubyGem package (.gem file)
2
+
3
+ Files:
4
+ * The name of the gemspec file to build
5
+
6
+ Arguments:
7
+ * (none)
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ git archive --prefix="$_prefix" -o $__build_dir/$1 ${_ref-HEAD}
@@ -0,0 +1,8 @@
1
+ Exports the Git repository using the git archive command.
2
+
3
+ Files:
4
+ * The filename of the exported Git archive.
5
+
6
+ Arguments:
7
+ * ref: a commit, branch, or tag to export.
8
+ * prefix: a prefix to append to every path in the exported archive.
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ git add $*
5
+ git commit -m "${_message-Bump version to v$_version}"
6
+ git tag ${_tag-v$_version}
7
+ echo tag ${_tag-v$_version} >> $__restore_file
@@ -0,0 +1,8 @@
1
+ Performs a commit on the working copy repository and tags the commit.
2
+
3
+ Files:
4
+ * The list of files to stage for commit.
5
+
6
+ Arguments:
7
+ * message: the commit message, defaults to "Bump version to vVERSION".
8
+ * tag: the tag name, defaults to vVERSION.
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ git fetch ${_remote-origin}
5
+ git checkout -q $_branch
6
+ echo branch $_branch $(git rev-parse HEAD) >> $__restore_file
7
+ git rebase ${_remote-origin}/$_branch
8
+ git merge $__build_branch -q -m "Merge release branch into $_branch" -s recursive -Xtheirs --ff
9
+ git checkout -q $__build_branch
@@ -0,0 +1,8 @@
1
+ Merges release branch into a destination branch.
2
+
3
+ Files:
4
+ * (none)
5
+
6
+ Arguments:
7
+ * branch: the destination branch to merge.
8
+ * remote: the remote to fetch before merging. Defaults to "origin".
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ npm test
@@ -0,0 +1,7 @@
1
+ Runs npm test on the working directory.
2
+
3
+ Files:
4
+ * (none)
5
+
6
+ Arguments:
7
+ * (none)
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ rake $_task
@@ -0,0 +1,7 @@
1
+ Runs a Rake task.
2
+
3
+ Files:
4
+ * (none)
5
+
6
+ Arguments:
7
+ * task: the task to execute.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV['AWS_ACCESS_KEY_ID'] = ENV['__creds_key']
4
+ ENV['AWS_SECRET_ACCESS_KEY'] = ENV['__creds_secret']
5
+
6
+ require 'aws-sdk-core'
7
+
8
+ Aws.config[:region] = ENV['_region']
9
+ Aws.cloudfront.create_invalidation(
10
+ distribution_id: ENV['_distribution'],
11
+ invalidation_batch: {
12
+ paths: {
13
+ quantity: ARGV.size,
14
+ items: ARGV },
15
+ caller_reference: Time.now.to_s
16
+ })
@@ -0,0 +1,8 @@
1
+ Invalidates a CloudFront distribution.
2
+
3
+ Files:
4
+ * A list of URIs to invalidate.
5
+
6
+ Arguments:
7
+ * distribution: The CloudFront distribution ID.
8
+ * region: The region of the CloudFront distribution.
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+
3
+ curl --fail --silent -X POST \
4
+ -H "Content-Type: application/octet-stream" \
5
+ -H "Authorization: $__creds_secret" \
6
+ --data-binary @$* https://rubygems.org/api/v1/gems
@@ -0,0 +1,7 @@
1
+ Publishes a RubyGem package (.gem file).
2
+
3
+ Files:
4
+ * The .gem file to publish.
5
+
6
+ Arguments:
7
+ * (none)
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ olddir=$(pwd)
5
+ dir=$(mktemp -d -t samus)
6
+
7
+ tar -xzf $* -C $dir
8
+
9
+ cd $dir
10
+ for r in $_remotes; do
11
+ git push $r $_refs
12
+ done
13
+ cd $olddir
14
+
15
+ rm -rf $dir
@@ -0,0 +1,8 @@
1
+ Pushes Git repository refs to a set of remotes.
2
+
3
+ Files:
4
+ * The repository archive filename.
5
+
6
+ Arguments:
7
+ * refs: a space delimited set of commits, branches, or tags to push.
8
+ * remotes: a space delimited set of remotes to push refs to.
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ npm publish --email=$__creds_key --_auth=$__creds_secret ./$*
@@ -0,0 +1,7 @@
1
+ Publishes an npm package.
2
+
3
+ Files:
4
+ * The filename of the archived npm package
5
+
6
+ Arguments:
7
+ * (none)
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+
3
+ export AWS_ACCESS_KEY_ID=$__creds_key
4
+ export AWS_SECRET_ACCESS_KEY=$__creds_secret
5
+
6
+ set -e
7
+ for f in $*; do
8
+ recursive=""
9
+ if [ -d $f ]; then
10
+ recursive="--recursive"
11
+ fi
12
+ aws s3 cp $recursive --acl public-read --region $_region $f s3://$_bucket/$_prefix$_key
13
+ done
@@ -0,0 +1,10 @@
1
+ Uploads files or directories to an Amazon S3 bucket.
2
+
3
+ Files:
4
+ * A list of files to upload to the S3 bucket.
5
+
6
+ Arguments:
7
+ * region: the region of the S3 bucket.
8
+ * bucket: the name of the S3 bucket.
9
+ * prefix: (optional) a path to prefix to the uploaded key names.
10
+ * key: (optional) a key prefix path.
@@ -0,0 +1,37 @@
1
+ require_relative './samus/publisher'
2
+ require_relative './samus/builder'
3
+
4
+ module Samus
5
+ CONFIG_PATH = File.expand_path(ENV['SAMUS_CONFIG_PATH'] || '~/.samus')
6
+
7
+ module_function
8
+
9
+ def config_paths; @@config_paths end
10
+
11
+ @@config_paths = []
12
+
13
+ def load_configuration_directory
14
+ if File.exist?(CONFIG_PATH)
15
+ Dir.foreach(CONFIG_PATH) do |dir|
16
+ next if dir == '.' || dir == '..'
17
+ dir = File.join(CONFIG_PATH, dir)
18
+ config_paths.unshift(dir) if File.directory?(dir)
19
+ end
20
+ end
21
+ end
22
+
23
+ def load_commands
24
+ config_paths.each do |path|
25
+ path = File.join(path, 'commands')
26
+ Samus::Command.command_paths.unshift(path) if File.directory?(path)
27
+ end
28
+ end
29
+
30
+ def error(msg)
31
+ puts "[E] #{msg}"
32
+ exit(1)
33
+ end
34
+ end
35
+
36
+ Samus.load_configuration_directory
37
+ Samus.load_commands
@@ -0,0 +1,60 @@
1
+ require_relative './command'
2
+ require_relative './credentials'
3
+
4
+ module Samus
5
+ class Action
6
+ def initialize(opts = {})
7
+ @raw_options = opts
8
+ @dry_run = opts[:dry_run]
9
+ @allow_fail = false
10
+ @command = nil
11
+ @creds = nil
12
+ @arguments = opts[:arguments] || {}
13
+ end
14
+
15
+ def stage; raise NotImplementedError, 'action must define stage' end
16
+
17
+ def load(opts = {})
18
+ opts.each do |key, value|
19
+ meth = "#{key}="
20
+ if respond_to?(meth)
21
+ send(meth, value)
22
+ else
23
+ Samus.error("Unknown action property: #{key}")
24
+ end
25
+ end
26
+ self
27
+ end
28
+
29
+ def run
30
+ @command.run(command_options) if @command
31
+ end
32
+
33
+ def command_options
34
+ {
35
+ :arguments => @creds ? @arguments.merge(@creds.load) : @arguments,
36
+ :files => @files,
37
+ :dry_run => @dry_run,
38
+ :allow_fail => @allow_fail
39
+ }
40
+ end
41
+
42
+ def action=(name)
43
+ @command = Command.new(stage, name)
44
+ end
45
+
46
+ def credentials=(key)
47
+ @creds = Credentials.new(key)
48
+ end
49
+
50
+ def allowFail=(value)
51
+ @allow_fail = value
52
+ end
53
+
54
+ attr_writer :files
55
+
56
+ def arguments=(args)
57
+ args.each {|k, v| @arguments[k] = v }
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
1
+ require_relative './action'
2
+
3
+ module Samus
4
+ class BuildAction < Action
5
+ def initialize(opts = {})
6
+ super(opts)
7
+ @pwd = nil
8
+ @skip = false
9
+ end
10
+
11
+ attr_reader :publish
12
+
13
+ def stage; 'build' end
14
+
15
+ def command_options
16
+ super.merge(:pwd => @pwd)
17
+ end
18
+
19
+ def pwd=(pwd)
20
+ @pwd = pwd
21
+ end
22
+
23
+ def run
24
+ return if @skip
25
+ super
26
+ end
27
+
28
+ def publish=(publish)
29
+ @publish = Array === publish ? publish : [publish]
30
+ @publish.each do |publish_action|
31
+ publish_action['files'] ||= @files if @files
32
+ end
33
+ @publish
34
+ end
35
+
36
+ attr_reader :skip
37
+ def condition=(condition)
38
+ begin
39
+ @skip = !eval(condition)
40
+ rescue => e
41
+ puts "[E] Condition failed on #{@raw_options['action']}"
42
+ raise e
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,101 @@
1
+ require 'json'
2
+ require 'tmpdir'
3
+
4
+ require_relative './build_action'
5
+
6
+ module Samus
7
+ class Builder
8
+ RESTORE_FILE = ".git/samus-restore"
9
+
10
+ attr_reader :build_manifest
11
+
12
+ def initialize(build_manifest_file)
13
+ @stage = 'build'
14
+ @build_manifest_file = build_manifest_file
15
+ @build_manifest = JSON.parse(File.read(build_manifest_file).gsub('$version', $VERSION))
16
+ @manifest = {}
17
+ end
18
+
19
+ def build(dry_run = false, zip_release = true)
20
+ orig_pwd = Dir.pwd
21
+ manifest = {'version' => $VERSION, 'actions' => []}
22
+ build_branch = "samus-release/v#{$VERSION}"
23
+ orig_branch = `git symbolic-ref -q --short HEAD`.chomp
24
+
25
+ system "git checkout -qb #{build_branch} 2>/dev/null"
26
+ remove_restore_file
27
+
28
+ Dir.mktmpdir do |build_dir|
29
+ actions.map do |action|
30
+ BuildAction.new(:dry_run => dry_run, :arguments => {
31
+ "_restore_file" => RESTORE_FILE,
32
+ "_build_dir" => build_dir,
33
+ "_build_branch" => build_branch,
34
+ "version" => $VERSION
35
+ }).load(action)
36
+ end.each do |action|
37
+ next if action.skip
38
+ action.run
39
+ manifest['actions'] += action.publish if action.publish
40
+ end
41
+
42
+ Dir.chdir(build_dir) do
43
+ generate_manifest(manifest)
44
+ generate_release(orig_pwd, zip_release)
45
+ end unless dry_run
46
+ end
47
+
48
+ ensure
49
+ restore_git_repo
50
+ system "git checkout -q #{orig_branch}"
51
+ system "git branch -qD #{build_branch}"
52
+ end
53
+
54
+ private
55
+
56
+ def generate_manifest(manifest)
57
+ File.open('manifest.json', 'w') do |f|
58
+ f.puts JSON.pretty_generate(manifest, indent: ' ')
59
+ end
60
+ end
61
+
62
+ def generate_release(orig_pwd, zip_release = true)
63
+ file = build_manifest['output'] || "release-v#{$VERSION}"
64
+ file = File.join(orig_pwd, file)
65
+ if zip_release
66
+ file += '.tar.gz'
67
+ system "tar cfz #{file} *"
68
+ else
69
+ system "mkdir -p #{file} && cp -r * #{file}"
70
+ end
71
+ puts "[I] Built release package: #{File.basename(file)}"
72
+ end
73
+
74
+ def actions
75
+ build_manifest['actions']
76
+ end
77
+
78
+ def restore_git_repo
79
+ return unless File.file?(RESTORE_FILE)
80
+
81
+ File.readlines(RESTORE_FILE).each do |line|
82
+ type, branch, commit = *line.split(/\s+/)
83
+ case type
84
+ when "tag"
85
+ puts "[D] Removing tag #{branch}" if $DEBUG
86
+ system "git tag -d #{branch} >/dev/null"
87
+ when "branch"
88
+ puts "[D] Restoring #{branch} to #{commit}" if $DEBUG
89
+ system "git checkout -q #{branch}"
90
+ system "git reset -q --hard #{commit}"
91
+ end
92
+ end
93
+ ensure
94
+ remove_restore_file
95
+ end
96
+
97
+ def remove_restore_file
98
+ File.unlink(RESTORE_FILE) if File.file?(RESTORE_FILE)
99
+ end
100
+ end
101
+ end