ebm 0.0.2

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.
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
+