ebm 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Copyright (c) 2013 eBay
data/bin/ebm ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # ebm - Ebay Mobile Gem
4
+ # this command is meant to be called after installed as a gem
5
+ #
6
+
7
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
8
+ require 'rubygems'
9
+ #require "bundler/setup"
10
+ require 'ebm'
11
+
12
+ exit_code = Ebm.new.run
13
+ exit!(exit_code)
14
+
15
+
@@ -0,0 +1,12 @@
1
+ #require "FileUtils"
2
+ require "set"
3
+
4
+ require 'ebmsharedlib/monkey_patches'
5
+ require "printer"
6
+ require "ebmsharedlib/options"
7
+ require "ebmsharedlib/utilities"
8
+
9
+
10
+ require 'commands/prepare'
11
+ require 'commands/list_configs'
12
+ require 'commands/make_sample'
@@ -0,0 +1,42 @@
1
+ module Commands
2
+ class ListConfigs
3
+
4
+ # holds the options that were passed
5
+ # you can set any initial defaults here
6
+ def options
7
+ @options ||= {
8
+ }
9
+ end
10
+
11
+ # required options
12
+ def required_options
13
+ @required_options ||= Set.new [
14
+ ]
15
+ end
16
+
17
+ def register(opts, global_options)
18
+ opts.banner = "Usage: list_configs"
19
+ opts.description = "List all possible configurations."
20
+ end
21
+
22
+
23
+ def run(global_options)
24
+ # show contents of configs directory for files with .config extension
25
+ config_path = "#{EbmSharedLib::CONFIG_PATH}/configs"
26
+ config_names = Pathname.glob("#{config_path}/*.config").map { |i|
27
+ if !i.directory?
28
+ name = i.basename.to_s
29
+ name.slice!("#{EbmSharedLib::CONFIG_SUFFIX}")
30
+ name
31
+ else
32
+ nil
33
+ end
34
+ }
35
+ config_names.each do |i|
36
+ puts i unless i.nil?
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,76 @@
1
+ module Commands
2
+ class MakeSample
3
+
4
+ # holds the options that were passed
5
+ # you can set any initial defaults here
6
+ def options
7
+ @options ||= {
8
+ }
9
+ end
10
+
11
+ # required options
12
+ def required_options
13
+ @required_options ||= Set.new [
14
+ :config,
15
+ ]
16
+ end
17
+
18
+ def register(opts, global_options)
19
+ opts.banner = "Usage: make_sample [options]"
20
+ opts.description = "Make a sample config file"
21
+
22
+ opts.on('-c', "--config name", "Required - Name of the config we are making.") do |v|
23
+ options[:config] = v
24
+ end
25
+
26
+ end
27
+
28
+
29
+ def run(global_options)
30
+
31
+ # create a sample config file in the current directory - we append the .config suffix
32
+ # the file will be in JSON format
33
+ config_name = options[:config]
34
+
35
+ config_path = "#{config_name}#{EbmSharedLib::CONFIG_SUFFIX}"
36
+
37
+ begin
38
+ sample = {
39
+ :repos => [
40
+ {
41
+ :branch => "iphone_3.1",
42
+ :create_dev_branch => true,
43
+ :git_path => "git@github.scm.corp.ebay.com:eBayMobile/ebaycore.git",
44
+ },
45
+ {
46
+ :branch => "iphone_3.1",
47
+ :create_dev_branch => true,
48
+ :git_path => "git@github.scm.corp.ebay.com:eBayMobile/ebaymobile_common.git",
49
+ },
50
+ {
51
+ :tag => "2.2.9",
52
+ :git_path => "git@github.scm.corp.ebay.com:ios-mobile-framework/CoreFramework.git",
53
+ :parent_path => "Framework",
54
+ },
55
+ {
56
+ :tag => "2.0.10",
57
+ :git_path => "git@github.scm.corp.ebay.com:ios-mobile-framework/ImagePickerModule.git",
58
+ :parent_path => "Framework/Modules",
59
+ },
60
+ {
61
+ :tag => "11fb35782f647a13552ccbd620ca4e88b75a8977",
62
+ :git_path => "git@github.scm.corp.ebay.com:cfry/RegistrationModule.git",
63
+ :parent_path => "Framework/Modules",
64
+ },
65
+ ],
66
+ }
67
+
68
+ json = JSON.pretty_generate(sample)
69
+
70
+ File.open(config_path, 'w') { |file| file.write(json) }
71
+ rescue
72
+ raise "Error creating config file JSON: #{config_path}"
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,128 @@
1
+ module Commands
2
+ class Prepare
3
+
4
+ # holds the options that were passed
5
+ # you can set any initial defaults here
6
+ def options
7
+ @options ||= {
8
+ }
9
+ end
10
+
11
+ # required options
12
+ def required_options
13
+ @required_options ||= Set.new [
14
+ :config,
15
+ :initials,
16
+ ]
17
+ end
18
+
19
+ def register(opts, global_options)
20
+ opts.banner = "Usage: prepare [options]"
21
+ opts.description = "Prepare your build environment"
22
+
23
+ opts.on('-c', "--config name", "Required - Name of the config we are preparing from.") do |v|
24
+ options[:config] = v
25
+ end
26
+
27
+ opts.on('-i', "--initials name", "Required - Initials prepended to your branch For example --initials gws will result in something like gws_iphone_3.0.") do |v|
28
+ options[:initials] = v
29
+ end
30
+
31
+ end
32
+
33
+ # prepare a single repo and create a local and tracking branch if it should have one
34
+ # if the repo specifies a branch then we will do the initial fetch from that branch
35
+ # if the create_dev_branch flag is set, we will create a local and tracking branch with
36
+ # the developer initials prepended
37
+ def prepare_repo(repo, top_dir, initials)
38
+ git_path = repo[:git_path]
39
+ branch = repo[:branch]
40
+ create_dev_branch = repo[:create_dev_branch]
41
+ tag = repo[:tag]
42
+ parent_path = repo[:parent_path]
43
+
44
+ if tag && branch
45
+ raise "We only support branching relative to HEAD, you cannot specify a branch:#{branch} and a tag:#{tag}."
46
+ end
47
+
48
+ if tag && create_dev_branch
49
+ raise "We do not support creating dev branches when using a tag"
50
+ end
51
+
52
+ # build the parent path if we have one and make it the new top dir
53
+ if parent_path
54
+ Dir.chdir(top_dir){
55
+ FileUtils.mkpath(parent_path)
56
+ }
57
+ top_dir = "#{top_dir}/#{parent_path}"
58
+ end
59
+
60
+ # first clone the repo
61
+ cmd = "git clone #{git_path}"
62
+ if EbmSharedLib::CL.do_cmd_result(cmd, top_dir) != 0
63
+ raise "Cloning repo at #{git_path} failed."
64
+ end
65
+
66
+ # extract the directory name that this repo ended up in
67
+ repo_name = git_path.split("/").last.split(".git")[0]
68
+ repo_path = "#{top_dir}/#{repo_name}"
69
+
70
+ # now set up the remote tracking base branch if we have one
71
+ if branch
72
+ cmd = "git checkout --track origin/#{branch}"
73
+ if EbmSharedLib::CL.do_cmd_result(cmd, repo_path) != 0
74
+ raise "Checking out branch #{branch} for #{repo_name} failed."
75
+ end
76
+
77
+ # now create the developer branch off of the base branch
78
+ if create_dev_branch
79
+ dev_branch_name = "#{initials}_#{branch}"
80
+ cmd = "git checkout -b #{dev_branch_name} && git push -u origin #{dev_branch_name}"
81
+ if EbmSharedLib::CL.do_cmd_result(cmd, repo_path) != 0
82
+ raise "Unable to create local and tracking developer branch #{dev_branch_name} for #{repo_name}."
83
+ end
84
+ end
85
+ elsif tag
86
+ # they are using a tag so don't create dev branches
87
+ cmd = "git checkout #{tag}"
88
+ if EbmSharedLib::CL.do_cmd_result(cmd, repo_path) != 0
89
+ raise "Unable to checkout tag:#{tag} for #{repo_name}."
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ def run(global_options)
96
+
97
+ # see if we can open the config file - we append the .config suffix
98
+ # the file is expected to be in JSON format
99
+ config_name = options[:config]
100
+ initials = options[:initials]
101
+
102
+ config_path = "#{EbmSharedLib::CONFIG_PATH}/configs/#{config_name}#{EbmSharedLib::CONFIG_SUFFIX}"
103
+
104
+ begin
105
+ json = File.open(config_path, 'r') {|f| f.read }
106
+ info = JSON.parse(json)
107
+ info.recursively_symbolize_keys!
108
+ rescue
109
+ raise "Error opening config file JSON: #{config_path}"
110
+ end
111
+
112
+ # Now that we have the json, prepare the world by creating a directory with the config name and placing
113
+ # the various repos beneath that. The directory is created relative to the current directory.
114
+
115
+ top_dir = "#{Dir.pwd}/#{config_name}"
116
+ raise "Cannot prepare since top level directory already exists: #{top_dir}" if File.directory?(top_dir)
117
+
118
+ Dir::mkdir(top_dir)
119
+
120
+ repos = info[:repos]
121
+ repos.each do |repo|
122
+ prepare_repo(repo, top_dir, initials)
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+ end
@@ -0,0 +1,161 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+
4
+ $:.unshift(File.dirname(__FILE__))
5
+ models = File.expand_path('../../models', __FILE__)
6
+ $:.unshift(models)
7
+ require 'subcommand'
8
+ require 'commands'
9
+ require 'json'
10
+ require 'info'
11
+
12
+ class Ebm
13
+ include Subcommands
14
+
15
+ CMD = "ebm"
16
+
17
+ # required options
18
+ def required_options
19
+ @required_options ||= Set.new [
20
+ ]
21
+ end
22
+
23
+ # the options that were set
24
+ def options
25
+ @options ||= {}
26
+ end
27
+
28
+ def sub_commands
29
+ @sub_commands ||= {}
30
+ end
31
+
32
+ def printer
33
+ EbmSharedLib.printer
34
+ end
35
+
36
+ # define sub commands here
37
+ def define_sub_commands
38
+ sub_commands[:prepare] = Commands::Prepare.new
39
+ sub_commands[:list_configs] = Commands::ListConfigs.new
40
+ sub_commands[:make_sample] = Commands::MakeSample.new
41
+ end
42
+
43
+ def setup
44
+ options.clear
45
+ # try to make sure the repo is available
46
+ EbmSharedLib.prepare_config_repo
47
+ # global options
48
+ global_options do |opts|
49
+ opts.banner = "Version: #{Info.version} - Usage: #{CMD} [options] [subcommand [options]]"
50
+ opts.description = "eBay Mobile configuration and deploy tool. You must specify a valid sub command."
51
+ opts.separator ""
52
+ opts.separator "Global options are:"
53
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
54
+ options[:verbose] = v
55
+ end
56
+
57
+ end
58
+ add_help_option
59
+
60
+ define_sub_commands
61
+
62
+ sub_commands.each_pair do |command_name, sub_cmd|
63
+ command command_name do |opts|
64
+ sub_cmd.send("register", opts, options)
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ def force_fail(cmd = nil)
71
+ # force failure and show options
72
+ ARGV.clear
73
+ ARGV << "help"
74
+ ARGV << cmd unless cmd.nil?
75
+ opt_parse
76
+ end
77
+
78
+ # validate the options passed
79
+ def validate(cmd, sub_cmd)
80
+ required_options.each do |r|
81
+ if options.has_key?(r) == false
82
+ puts "Missing options"
83
+ force_fail
84
+ end
85
+ end
86
+
87
+ sub_cmd.required_options.each do |r|
88
+ if sub_cmd.options.has_key?(r) == false
89
+ puts "Missing options"
90
+ force_fail(cmd)
91
+ end
92
+ end
93
+ end
94
+
95
+ def parse
96
+ if ARGV.empty?
97
+ ARGV << "help"
98
+ end
99
+
100
+ cmd = opt_parse()
101
+ if cmd.nil?
102
+ force_fail
103
+ end
104
+
105
+ # ok, we have a valid command so dispatch it
106
+ # puts "cmd: #{cmd}"
107
+ # puts "options ......"
108
+ # p options
109
+ # puts "ARGV:"
110
+ # p ARGV
111
+
112
+ sub_cmd = sub_commands[cmd.to_sym]
113
+ validate(cmd, sub_cmd)
114
+
115
+ # track both types of options
116
+ EbmSharedLib::Options.global_options = options
117
+ EbmSharedLib::Options.cmd_options = sub_cmd.options
118
+
119
+ sub_cmd.send("run", options)
120
+ end
121
+
122
+
123
+
124
+ def run(argv = ARGV)
125
+ exit_code = true
126
+ begin
127
+ setup
128
+ parse
129
+ rescue SystemExit => ex
130
+ # ignore direct calls to exit
131
+ rescue Exception => ex
132
+ printer.error printer.color(ex.message, :red)
133
+ # puts ex.backtrace
134
+ exit_code = false
135
+ end
136
+
137
+ # make sure buffer is flushed
138
+ # debugger doesn't seem to do this always
139
+ STDOUT.flush
140
+
141
+ return exit_code
142
+ end
143
+
144
+ def print_actions
145
+ cmdtext = "Commands are:"
146
+ @commands.sort.map do |c, opt|
147
+ #puts "inside opt.call loop"
148
+ desc = opt.call.description
149
+ cmdtext << "\n #{c} : #{desc}"
150
+ end
151
+
152
+ # print aliases
153
+ unless @aliases.empty?
154
+ cmdtext << "\n\nAliases: \n"
155
+ @aliases.each_pair { |name, val| cmdtext << " #{name} - #{val}\n" }
156
+ end
157
+
158
+ cmdtext << "\n\nSee '#{CMD} help COMMAND' for more information on a specific command."
159
+ end
160
+
161
+ end
@@ -0,0 +1,26 @@
1
+ class Hash
2
+ # A method to recursively symbolize all keys in the Hash class
3
+ # lets you access keys via symbols such as :the_key instead of
4
+ # strings such as "the_key"
5
+ #
6
+ def recursively_symbolize_keys!
7
+ self.symbolize_keys!
8
+ self.values.each do |v|
9
+ if v.is_a? Hash
10
+ v.recursively_symbolize_keys!
11
+ elsif v.is_a? Array
12
+ v.each do |a|
13
+ a.recursively_symbolize_keys! if a.is_a? Hash
14
+ end
15
+ end
16
+ end
17
+ self
18
+ end
19
+
20
+ def symbolize_keys!
21
+ keys.each do |key|
22
+ self[(key.to_sym rescue key) || key] = delete(key)
23
+ end
24
+ self
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module EbmSharedLib
2
+ # tracks the global and per command options but lets you
3
+ # fetch values without regard to which one. The command
4
+ # is checked before the global
5
+ class Options
6
+ def self.global_options=(options)
7
+ @@global_options = options
8
+ end
9
+
10
+ def self.cmd_options=(options)
11
+ @@cmd_options = options
12
+ end
13
+
14
+ def self.cmd_options
15
+ @@cmd_options ||= {}
16
+ end
17
+
18
+ def self.global_options
19
+ @@global_options ||= {}
20
+ end
21
+
22
+ def self.get(option)
23
+ v = cmd_options[option]
24
+ return v if !v.nil?
25
+
26
+ v = global_options[option]
27
+ return v
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,58 @@
1
+ module EbmSharedLib
2
+ ROOT_PATH = File.expand_path("~/.ebm")
3
+ CONFIG_DIR = "build_configs"
4
+ CONFIG_PATH = "#{ROOT_PATH}/#{CONFIG_DIR}"
5
+ CONFIG_SUFFIX = ".config"
6
+
7
+ class CL
8
+ # run a command line and echo to console
9
+ # returns 0 on no error, otherwise the error number
10
+ def self.do_cmd(cmd, dir=nil)
11
+ exit_code = 0
12
+
13
+ puts cmd
14
+ begin
15
+ if !dir.nil?
16
+ Dir.chdir(dir){
17
+ Kernel.system(cmd)
18
+ }
19
+ else
20
+ Kernel.system(cmd)
21
+ end
22
+ rescue Exception => ex
23
+ exit_code = 100 #indicate an error, probably due to invalid dir
24
+ end
25
+
26
+ exit_code = $?.exitstatus if exit_code == 0
27
+
28
+ exit_code
29
+ end
30
+
31
+ # same as above but returns the result code
32
+ # 0 is success, anything else is an error code
33
+ def self.do_cmd_result(cmd, dir=nil)
34
+ do_cmd(cmd, dir)
35
+ end
36
+ end
37
+
38
+ def self.prepare_config_repo
39
+ # make the root if missing
40
+ `mkdir -p #{ROOT_PATH}`
41
+
42
+ # try to pull, if it fails could be due to repo not cloned
43
+ cmd = "git pull"
44
+ if EbmSharedLib::CL.do_cmd_result(cmd, CONFIG_PATH) != 0
45
+ # pull failed, try to clone
46
+ cmd = "git clone git@github.scm.corp.ebay.com:eBayMobile/build_configs.git"
47
+ if EbmSharedLib::CL.do_cmd_result(cmd, ROOT_PATH) != 0
48
+ raise "Unable to clone build_configs repo into #{ROOT_PATH}"
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ def self.printer
55
+ @printer ||= Printer.new
56
+ end
57
+
58
+ end
@@ -0,0 +1,5 @@
1
+ class Info
2
+ def self.version
3
+ "0.0.2"
4
+ end
5
+ end
@@ -0,0 +1,54 @@
1
+ class Printer
2
+ attr_reader :stdout
3
+ attr_reader :stderr
4
+ attr_reader :stdin
5
+
6
+ def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN)
7
+ @stdout, @stderr, @stdin = stdout, stderr, stdin
8
+ end
9
+
10
+ def highline
11
+ @highline ||= begin
12
+ require 'highline'
13
+ HighLine.new
14
+ end
15
+ end
16
+
17
+ # Prints a message to stdout. Aliased as +info+ for compatibility with
18
+ # the logger API.
19
+ def msg(message)
20
+ stdout.puts message
21
+ stdout.flush
22
+ end
23
+
24
+ alias :info :msg
25
+
26
+ # Print a warning message
27
+ def warn(message)
28
+ msg("#{color('WARNING:', :yellow, :bold)} #{message}")
29
+ end
30
+
31
+ # Print an error message
32
+ def error(message)
33
+ msg("#{color('ERROR:', :red, :bold)} #{message}")
34
+ end
35
+
36
+ # Print a message describing a fatal error.
37
+ def fatal(message)
38
+ msg("#{color('FATAL:', :red, :bold)} #{message}")
39
+ end
40
+
41
+ def color(string, *colors)
42
+ if color?
43
+ highline.color(string, *colors)
44
+ else
45
+ string
46
+ end
47
+ end
48
+
49
+ # Should colored output be used? Only on TTY
50
+ def color?
51
+ true
52
+ end
53
+
54
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ebm
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Greg Seitz
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-05-03 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: subcommand
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ - 0
31
+ version: 1.0.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: json
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 5
44
+ - 2
45
+ version: 1.5.2
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: highline
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 6
58
+ - 2
59
+ version: 1.6.2
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ description: Allows configuration of various build systems for eBay mobile
63
+ email:
64
+ executables:
65
+ - ebm
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - lib/commands/list_configs.rb
72
+ - lib/commands/make_sample.rb
73
+ - lib/commands/prepare.rb
74
+ - lib/commands.rb
75
+ - lib/ebm.rb
76
+ - lib/ebmsharedlib/monkey_patches.rb
77
+ - lib/ebmsharedlib/options.rb
78
+ - lib/ebmsharedlib/utilities.rb
79
+ - lib/info.rb
80
+ - lib/printer.rb
81
+ - bin/ebm
82
+ - LICENSE
83
+ has_rdoc: true
84
+ homepage:
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options:
89
+ - --charset=UTF-8
90
+ require_paths:
91
+ - lib
92
+ - lib/commands
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 1
99
+ - 8
100
+ version: "1.8"
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 1
107
+ - 3
108
+ version: "1.3"
109
+ requirements: []
110
+
111
+ rubyforge_project:
112
+ rubygems_version: 1.3.6
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: eBay Mobile build tools
116
+ test_files: []
117
+