maguro 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ddeb4fe9eb84bdeb224b00749cd640703f104dd4
4
+ data.tar.gz: 5912a8b3ad6fa2f659dc7eb0ed4c380914f677d2
5
+ SHA512:
6
+ metadata.gz: 007ce4f75281f70fe5c536cb3513259243a2119edd518ed665614b65312530fbe05c6ef7671ef3d498de67545056a171f3c9a0eb288acdea1f4faaefe433fd81
7
+ data.tar.gz: e148cb85c274c7f13d0f42c0839ab88c71d2648da655dc297d5ff1f508e9f249545faab453ef438aca1eca05afd97951cb0dd9199f83e9679af110d1de1fcee0
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .idea
3
+ config.yaml
4
+ maguro-*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1 @@
1
+ magurogemset
@@ -0,0 +1 @@
1
+ 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gem_template.gemspec
4
+ gemspec
@@ -0,0 +1,102 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ maguro (0.0.1)
5
+ rails (= 4.1.8)
6
+ thor (~> 0.19)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.1.8)
12
+ actionpack (= 4.1.8)
13
+ actionview (= 4.1.8)
14
+ mail (~> 2.5, >= 2.5.4)
15
+ actionpack (4.1.8)
16
+ actionview (= 4.1.8)
17
+ activesupport (= 4.1.8)
18
+ rack (~> 1.5.2)
19
+ rack-test (~> 0.6.2)
20
+ actionview (4.1.8)
21
+ activesupport (= 4.1.8)
22
+ builder (~> 3.1)
23
+ erubis (~> 2.7.0)
24
+ activemodel (4.1.8)
25
+ activesupport (= 4.1.8)
26
+ builder (~> 3.1)
27
+ activerecord (4.1.8)
28
+ activemodel (= 4.1.8)
29
+ activesupport (= 4.1.8)
30
+ arel (~> 5.0.0)
31
+ activesupport (4.1.8)
32
+ i18n (~> 0.6, >= 0.6.9)
33
+ json (~> 1.7, >= 1.7.7)
34
+ minitest (~> 5.1)
35
+ thread_safe (~> 0.1)
36
+ tzinfo (~> 1.1)
37
+ arel (5.0.1.20140414130214)
38
+ builder (3.2.2)
39
+ diff-lcs (1.2.5)
40
+ erubis (2.7.0)
41
+ hike (1.2.3)
42
+ i18n (0.6.11)
43
+ json (1.8.1)
44
+ mail (2.6.3)
45
+ mime-types (>= 1.16, < 3)
46
+ mime-types (2.4.3)
47
+ minitest (5.4.3)
48
+ multi_json (1.10.1)
49
+ rack (1.5.2)
50
+ rack-test (0.6.2)
51
+ rack (>= 1.0)
52
+ rails (4.1.8)
53
+ actionmailer (= 4.1.8)
54
+ actionpack (= 4.1.8)
55
+ actionview (= 4.1.8)
56
+ activemodel (= 4.1.8)
57
+ activerecord (= 4.1.8)
58
+ activesupport (= 4.1.8)
59
+ bundler (>= 1.3.0, < 2.0)
60
+ railties (= 4.1.8)
61
+ sprockets-rails (~> 2.0)
62
+ railties (4.1.8)
63
+ actionpack (= 4.1.8)
64
+ activesupport (= 4.1.8)
65
+ rake (>= 0.8.7)
66
+ thor (>= 0.18.1, < 2.0)
67
+ rake (10.3.2)
68
+ rspec (3.1.0)
69
+ rspec-core (~> 3.1.0)
70
+ rspec-expectations (~> 3.1.0)
71
+ rspec-mocks (~> 3.1.0)
72
+ rspec-core (3.1.7)
73
+ rspec-support (~> 3.1.0)
74
+ rspec-expectations (3.1.2)
75
+ diff-lcs (>= 1.2.0, < 2.0)
76
+ rspec-support (~> 3.1.0)
77
+ rspec-mocks (3.1.3)
78
+ rspec-support (~> 3.1.0)
79
+ rspec-support (3.1.2)
80
+ sprockets (2.11.3)
81
+ hike (~> 1.2)
82
+ multi_json (~> 1.0)
83
+ rack (~> 1.0)
84
+ tilt (~> 1.1, != 1.3.0)
85
+ sprockets-rails (2.2.1)
86
+ actionpack (>= 3.0)
87
+ activesupport (>= 3.0)
88
+ sprockets (>= 2.8, < 4.0)
89
+ thor (0.19.1)
90
+ thread_safe (0.3.4)
91
+ tilt (1.4.1)
92
+ tzinfo (1.2.2)
93
+ thread_safe (~> 0.1)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ bundler (~> 1.6)
100
+ maguro!
101
+ rake
102
+ rspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Haji Furukawa
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ # Maguro
2
+
3
+ ![alt tag](http://hajimefurukawa.com/random/img/maguro_sushi.jpg)
4
+
5
+ Maguro is the base Rails application used at [Bottega8](http://www.bottega8.com/).
6
+
7
+ It's goal is to do all the boring configuration of setting up a new project for you automatically,
8
+ so you can get to the fun development part in seconds instead of hours.
9
+
10
+ ## What does the template do?
11
+
12
+ Maguro will create a basic Rails project that is optimized for Bottega8's workflow by:
13
+
14
+ 1. Saving RVM configuration files
15
+ 1. Creating a basic README.md
16
+ 1. Setting up local git repository, gitinit file, and development branch
17
+ 1. Generating app_environment_variables.rb for custom environment variables
18
+ 1. Removing Turbolinks
19
+ 1. Including RSpec, capybara, database_cleaner, factory_girl, and other gems for testing
20
+ 1. Using PostgreSQL as the database and generating database.yml
21
+
22
+ Optionally, Maguro can also
23
+
24
+ 1. Create a Heroku application for staging and production environments
25
+ 1. Create a Git repository on Github.com, and pushing the newly-created Rails project to it
26
+ 1. Create a Git repository on BitBucket.org, and pushing the newly-created Rails project to it
27
+ 1. Securely store BitBucket.org credentials in the OS X keychain for convenience
28
+ 1. Create a local postgres database for the project
29
+
30
+ ## Gem Prerequisites
31
+
32
+ Before running Maguro:
33
+
34
+ 1. Install [PostgreSQL for OS X](http://www.postgresql.org/download/macosx/)
35
+ 1. Install Ruby. We recommend using the [Ruby Version Manager](http://rvm.io/rvm/install)
36
+
37
+
38
+ Optional:
39
+
40
+ 1. [Heroku toolbelt](https://toolbelt.heroku.com/) if you want to automatically deploy to heroku.
41
+ 1. [Hub](https://github.com/github/hub) if you want to create a remote repository on github.
42
+ `brew install hub` with [homebrew](http://brew.sh/).
43
+ 1. OSX Keychain if you want to save your bitbucket credentials.
44
+
45
+ ## Gem Usage
46
+
47
+ Install the gem:
48
+
49
+ `gem install maguro`
50
+
51
+ Create a new app:
52
+
53
+ `maguro new $APP_NAME`
54
+
55
+ ### Detailed Usage
56
+
57
+ 1. Switch to directory where new project will live. E.g. `cd ~/Desktop/projects`
58
+ 1. Install the maguro gem `gem install maguro`
59
+ 1. Generate the new project: `maguro new $APP_NAME`
60
+ 1. Open config/database.yml and replace `username` with the same username when setting up Postgres
61
+ 1. Run `rake db:create db:migrate`
62
+
63
+
64
+ ## Development and testing steps
65
+
66
+ To make local changes to this gem, clone this repository then:
67
+
68
+ 1. Clone this repository
69
+ 1. Run `bundle install` to install development dependencies
70
+ 1. Develop/modify the source code
71
+ 1. Run unit and integration tests with `rspec`
72
+ 1. Build the gem `gem build maguro.gemspec`
73
+ 1. Switch to the directory where you want to create a new project. E.g. `cd ~/Desktop/projects`
74
+ 1. Install the gem `gem install ./maguro-0.0.1.gem`
75
+ 1. Follow instructions in the section `Gem Usage`, i.e. `maguro new [APP_NAME]`
76
+
77
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # read about this someplace on stackoverflow so that we cna run this file directly and debug
5
+ # instead of having to rebuild and run the gem.
6
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
7
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
8
+
9
+ require 'maguro'
10
+
11
+ # required to set our custom AppGenerator source_path to the Rail's AppGenerator
12
+ # so it can find all default the template files.
13
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
14
+ Maguro::AppGenerator.source_root templates_root
15
+ Maguro::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root
16
+
17
+ #Start our custom CLI
18
+ Maguro::Cli.start(ARGV)
@@ -0,0 +1,9 @@
1
+ require 'maguro/app_generator'
2
+ require 'maguro/bitbucket'
3
+ require 'maguro/cli'
4
+ require 'maguro/features'
5
+ require 'maguro/gemfile'
6
+ require 'maguro/github'
7
+ require 'maguro/heroku'
8
+ require 'maguro/keychain'
9
+ require 'maguro/version'
@@ -0,0 +1,113 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/app/app_generator'
3
+
4
+ module Maguro
5
+ class AppGenerator < Rails::Generators::AppGenerator
6
+
7
+
8
+
9
+ class_option :heroku, type: :boolean, aliases: '--hh',
10
+ desc: 'Create a production and staging heroku application'
11
+
12
+ class_option :bitbucket, type: :boolean, aliases: '--bb',
13
+ desc: 'Create a bitbucket project and push to it.'
14
+
15
+ class_option :github, type: :boolean, aliases: '--gh',
16
+ desc: 'Create a github project and push to it.'
17
+
18
+ class_option :organization, type: :string, aliases: '-o',
19
+ desc: 'Pass in your organization name to be used by heroku and bitbucket'
20
+
21
+ class_option :'database-username', type: :string, aliases: '--du',
22
+ desc: 'Add a database username'
23
+
24
+ class_option :'database-password', type: :string, aliases: '--dp',
25
+ desc: 'Add a database password'
26
+
27
+ # Overriding Rails::Generators::AppGenerator#finish_template.
28
+ # Allows maguro to do stuff before the default rails generator is run.
29
+ #
30
+ def initialize(*args)
31
+ super
32
+
33
+ check_ruby_version
34
+
35
+ # Thor's option hash is frozen. Unfreeze so we can update our own variables on it.
36
+ # Risk: Don't accidentally modify options you didn't mean to!
37
+ self.options = options.dup
38
+
39
+ set_custom_options
40
+ end
41
+
42
+
43
+ # Overriding Rails::Generators::AppGenerator#finish_template.
44
+ # This will run our maguro customizations after all of the default rails customizations.
45
+ def finish_template
46
+ Maguro::Features.new(builder).run_all_updates
47
+
48
+ super
49
+ end
50
+
51
+ protected
52
+
53
+ def check_ruby_version
54
+ if ::RUBY_VERSION != Maguro::RUBY_VERSION
55
+ raise Thor::Error, "You are using ruby version #{::RUBY_VERSION}. Maguro requires ruby version #{Maguro::RUBY_VERSION}. (e.g. rvm use #{Maguro::RUBY_VERSION})."
56
+ end
57
+ end
58
+
59
+ def set_custom_options
60
+
61
+ #skip heroku and bitbucket if --pretend is passed.
62
+ if options[:pretend]
63
+ options[:heroku] = false
64
+ options[:bitbucket] = false
65
+ options[:github] = false
66
+ else
67
+ # Prompt user if they haven't passed in a value for heroku, bitbucket options.
68
+ if options[:heroku].nil?
69
+ options[:heroku] = builder.yes?('Setup Heroku (y/n)?')
70
+ end
71
+ if options[:bitbucket].nil?
72
+ options[:bitbucket] = builder.yes?('Setup BitBucket repo (y/n)?')
73
+ end
74
+ if options[:github].nil?
75
+ options[:github] = builder.yes?('Setup Github repo (y/n)?')
76
+ end
77
+ end
78
+
79
+ if options[:bitbucket] && options[:github]
80
+ raise Thor::Error, "Can't set up both bitbucket and github :p. (Select one)"
81
+ end
82
+
83
+ # only worry about setting organization if we are using heroku or bitbucket
84
+ if options[:heroku] || options[:bitbucket] || options[:github]
85
+ set_organization
86
+ end
87
+ end
88
+
89
+
90
+ KEYCHAIN_ORGANIZATION='organization'
91
+
92
+ def set_organization
93
+ saved_organization = Keychain.retrieve_account(KEYCHAIN_ORGANIZATION)
94
+ saved_organization = saved_organization[:password] if saved_organization
95
+
96
+ if options[:organization]
97
+ org_output = saved_organization ? saved_organization : "<none>"
98
+
99
+ if yes?("Save organization '#{options[:organization]}' as default (y/n)? (current default: #{org_output})")
100
+ Keychain.add_account(KEYCHAIN_ORGANIZATION, KEYCHAIN_ORGANIZATION, options[:organization])
101
+ end
102
+ elsif saved_organization
103
+ if yes?("Use saved organization, #{saved_organization} (y/n)?")
104
+ options[:organization] = saved_organization
105
+ else
106
+ raise Thor::InvocationError, "Organization was not set. Please set organization with '-o ORGANIZATION'"
107
+ end
108
+ else
109
+ raise Thor::InvocationError, "Organization was not set. Please set organization with '-o ORGANIZATION'"
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,185 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+ require 'json'
5
+
6
+ module Maguro
7
+ class Bitbucket
8
+ protected
9
+ attr_accessor :username, :password
10
+
11
+ public
12
+ attr_reader :builder, :app_name, :organization
13
+
14
+ BITBUCKET = "bitbucket.org"
15
+ API_BASE = "https://api.bitbucket.org/2.0"
16
+
17
+ def initialize(builder, app_name, organization)
18
+ @builder = builder
19
+ @app_name = app_name
20
+ @organization = organization
21
+ self.username = nil
22
+ self.password = nil
23
+ end
24
+
25
+ def git_url
26
+ if @git_url.nil?
27
+ path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
28
+ response = bitbucket_api(path, Net::HTTP::Get)
29
+
30
+ if response.code == "200"
31
+ @git_url = JSON.parse(response.body)["links"]["clone"].find{|i| i["name"] == "https"}["href"]
32
+ else
33
+ raise "Could not retrieve Git url for project #{app_name}"
34
+ end
35
+ end
36
+ @git_url
37
+ end
38
+
39
+ def create_repo
40
+ options = {
41
+ scm: 'git',
42
+ name: app_name,
43
+ is_private: true,
44
+ fork_policy: 'no_public_forks',
45
+ language: 'ruby'
46
+ }
47
+
48
+ path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
49
+ response = bitbucket_api(path, Net::HTTP::Post, options)
50
+
51
+ if response.code == "200"
52
+ # Success
53
+ puts "Successfully created repository for #{app_name}"
54
+ else
55
+ raise "Could not create Git repository for project #{app_name}"
56
+ end
57
+ end
58
+
59
+ def delete_repo
60
+ path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
61
+ success_code = 204
62
+ response = bitbucket_api(path, Net::HTTP::Delete, {}, success_code)
63
+ raise "Could not delete repository." if response.code != success_code.to_s
64
+ puts "Successfully deleted repository: '#{app_name}'"
65
+ end
66
+
67
+ def get_repo
68
+ path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
69
+ response = bitbucket_api(path, Net::HTTP::Get)
70
+
71
+ # Do not raise on error, so that this method can be used
72
+ # to query the existence of a repository
73
+ return nil if response.code != "200"
74
+
75
+ JSON.parse(response.body)
76
+ end
77
+
78
+
79
+ private
80
+ def bitbucket_api(path, method, options = {}, expected_http_code = 200)
81
+ puts "Making request to API at: #{path} via #{method} with options: #{options}"
82
+
83
+ # TODO: Doug: do we want to enable this?
84
+ # First, try to read the username and password from the OS X Keychain,
85
+ # as stored by git credential-oskeychain
86
+ # if username.nil? || password.nil?
87
+ # output = %x[printf protocol=https\\\\nhost=#{BITBUCKET}\\\\n\\\\n | git credential-osxkeychain get]
88
+ # m = output.match("password=(.*)\n")
89
+ # self.password = m[1] if !m.nil?
90
+ # m = output.match("username=(.*)\n")
91
+ # self.username = m[1] if !m.nil?
92
+ # end
93
+
94
+ # Try to retrieve username and password directly from the OS X Keychain
95
+ did_get_password_from_keychain = false
96
+ if username.nil? || password.nil?
97
+ credentials = Keychain.retrieve_account(BITBUCKET)
98
+ if !credentials.nil?
99
+ self.username = credentials[:username]
100
+ self.password = credentials[:password]
101
+ did_get_password_from_keychain = true
102
+ end
103
+ end
104
+
105
+ tries = 0
106
+ response = nil
107
+ should_store_in_keychain = false
108
+
109
+ loop do
110
+
111
+ tries += 1
112
+
113
+ if username.nil? || password.nil?
114
+
115
+ # Prompt the user for password
116
+ puts ""
117
+ self.username = builder.ask "What is your BitBucket username?"
118
+ puts ""
119
+ # password = $stdin.noecho do
120
+ # ask "BitBucket password?"
121
+ # end
122
+ self.password = builder.ask "What is your BitBucket password?", :echo => false
123
+ puts ""
124
+ puts ""
125
+
126
+ if did_get_password_from_keychain || (builder.yes? "Do you want to store this BitBucket login info into the Keychain? (y/n)")
127
+ should_store_in_keychain = true
128
+ end
129
+ puts ""
130
+ end
131
+
132
+ url = URI.parse(path)
133
+ http = Net::HTTP.new(url.host, url.port)
134
+ http.use_ssl = (url.scheme == 'https')
135
+
136
+ request = method.new(url.path)
137
+ if !options.empty?
138
+ request["content-type"] = "application/json"
139
+ request.body = options.to_json
140
+ end
141
+
142
+ request.basic_auth username, password
143
+
144
+ response = http.request(request)
145
+
146
+ response_code = response.code.to_i
147
+
148
+ # Most REST calls return HTTP 200 on success.
149
+ # Some calls return another status code on success,
150
+ # E.g. DELETE returns 204
151
+ if response_code == expected_http_code # Success
152
+ Keychain.add_account(BITBUCKET, username, password) if should_store_in_keychain
153
+ return response
154
+ end
155
+
156
+ puts "Response code: #{response_code} message: #{response.message}"
157
+ if !response.body.empty?
158
+ message = JSON.parse(response.body)["error"]["message"]
159
+ detail = JSON.parse(response.body)["error"]["detail"]
160
+ puts "Error message: #{message}"
161
+ puts "Error detail: #{detail}" if !detail.nil?
162
+ end
163
+
164
+ break if tries >= 3 # Try no more than three times
165
+ break if response_code != 401 # Only retry when the username/password is incorrect
166
+
167
+ # Clear password, so the next iteration of the loop will prompt the user
168
+ if response_code == 401
169
+ self.username = nil
170
+ self.password = nil
171
+
172
+ if did_get_password_from_keychain
173
+ # If we got credentials from the Keychain, and authentication fails,
174
+ # clear the credentials from the keychain
175
+ Keychain.delete_account(BITBUCKET)
176
+ end
177
+ end
178
+ end
179
+
180
+ # The request was unsuccessful
181
+ response
182
+ end
183
+ end
184
+
185
+ end