maguro 0.0.1

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