├── .ruby-version ├── .rubocop.yml ├── templates ├── dotfiles │ ├── .ctags │ └── .env.example ├── rack_mini_profiler.rb ├── spec │ ├── shoulda_matchers.rb │ └── database_rewinder.rb ├── rubocop.yml.erb ├── overcommit.yml.erb ├── spec_helper.rb ├── rails_helper.rb ├── gitignore.erb ├── deploy.rb.erb ├── Gemfile.erb ├── gitlab-ci.yml.erb └── README.md.erb ├── .rspec ├── .travis.yml ├── bin ├── setup └── console ├── Rakefile ├── spec ├── bankai_spec.rb └── spec_helper.rb ├── .gitignore ├── Gemfile ├── lib ├── bankai │ ├── version.rb │ ├── generators │ │ ├── ci_generator.rb │ │ ├── json_generator.rb │ │ ├── base.rb │ │ ├── mailer_generator.rb │ │ ├── db_optimizations_generator.rb │ │ ├── lint_generator.rb │ │ ├── whenever_generator.rb │ │ ├── testing_generator.rb │ │ ├── sitemap_generator.rb │ │ └── deploy_generator.rb │ ├── helper.rb │ ├── builder.rb │ └── generator.rb └── bankai.rb ├── .overcommit.yml ├── exe └── bankai ├── bankai.gemspec ├── .gitlab-ci.yml ├── README.md └── CODE_OF_CONDUCT.md /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.6 2 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | SuggestExtensions: false 3 | -------------------------------------------------------------------------------- /templates/dotfiles/.ctags: -------------------------------------------------------------------------------- 1 | --recurse=yes 2 | --exclude=vendor 3 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /templates/dotfiles/.env.example: -------------------------------------------------------------------------------- 1 | ASSET_HOST=localhost:3000 2 | APPLICATION_HOST=localhost:3000 3 | PORT=3000 4 | RACK_MINI_PROFILER=0 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | sudo: false 3 | language: ruby 4 | cache: bundler 5 | rvm: 6 | - 2.7.4 7 | before_install: gem install bundler -v 2.2.26 8 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rspec/core/rake_task' 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | -------------------------------------------------------------------------------- /spec/bankai_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe Bankai do 4 | it 'has a version number' do 5 | expect(Bankai::VERSION).not_to be nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | 10 | # rspec failure tracking 11 | .rspec_status 12 | 13 | Gemfile.lock 14 | -------------------------------------------------------------------------------- /templates/rack_mini_profiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ENV['RACK_MINI_PROFILER'].to_i.positive? 4 | require 'rack-mini-profiler' 5 | 6 | Rack::MiniProfilerRails.initialize!(Rails.application) 7 | end 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # Specify your gem's dependencies in bankai.gemspec 8 | gemspec 9 | -------------------------------------------------------------------------------- /templates/spec/shoulda_matchers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Shoulda::Matchers.configure do |config| 4 | config.integrate do |with| 5 | with.test_framework :rspec 6 | with.library :rails 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/bankai/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bankai 4 | VERSION = '0.13.1' 5 | RUBY_VERSION = '2.6.7' 6 | RAILS_VERSION = '7.0.0' 7 | RUBOCOP_VERSION = '1.24.1' 8 | CAPISTRANO_VERSION = '3.16.0' 9 | end 10 | -------------------------------------------------------------------------------- /templates/spec/database_rewinder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.before(:suite) do 5 | DatabaseRewinder.clean_all 6 | end 7 | 8 | config.after do 9 | DatabaseRewinder.clean 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bankai/generators/ci_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class CiGenerator < Base 9 | class_option :api, type: :boolean, default: false 10 | 11 | def configure_ci 12 | template 'gitlab-ci.yml.erb', '.gitlab-ci.yml' 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require 'bankai' 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require 'irb' 15 | IRB.start(__FILE__) 16 | -------------------------------------------------------------------------------- /lib/bankai/generators/json_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class JsonGenerator < Base 9 | def add_oj 10 | gem 'oj' 11 | execute_command :bundle, 'install' 12 | 13 | initializer 'oj.rb' do 14 | "# frozen_string_literal: true\n\n" \ 15 | 'Oj.optimize_rails' 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/bankai/helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bankai 4 | # :nodoc: 5 | module Helper 6 | protected 7 | 8 | def pg? 9 | gemfile.match?(/gem .pg./) 10 | end 11 | 12 | def mysql? 13 | gemfile.match?(/gem .mysql2./) 14 | end 15 | 16 | def capistrano? 17 | gemfile.match?(/gem .capistrano./) 18 | end 19 | 20 | private 21 | 22 | def gemfile 23 | @gemfile ||= File.read("#{destination_root}/Gemfile") 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/setup' 4 | require 'simplecov' 5 | SimpleCov.start do 6 | load_profile 'test_frameworks' 7 | end 8 | require 'bankai' 9 | 10 | RSpec.configure do |config| 11 | # Enable flags like --only-failures and --next-failure 12 | config.example_status_persistence_file_path = '.rspec_status' 13 | 14 | # Disable RSpec exposing methods globally on `Module` and `main` 15 | config.disable_monkey_patching! 16 | 17 | config.expect_with :rspec do |c| 18 | c.syntax = :expect 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/bankai.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bankai/version' 4 | require 'bankai/generator' 5 | require 'bankai/helper' 6 | require 'bankai/generators/testing_generator' 7 | require 'bankai/generators/ci_generator' 8 | require 'bankai/generators/json_generator' 9 | require 'bankai/generators/db_optimizations_generator' 10 | require 'bankai/generators/mailer_generator' 11 | require 'bankai/generators/deploy_generator' 12 | require 'bankai/generators/lint_generator' 13 | require 'bankai/generators/sitemap_generator' 14 | require 'bankai/generators/whenever_generator' 15 | require 'bankai/builder' 16 | -------------------------------------------------------------------------------- /templates/rubocop.yml.erb: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-performance 3 | - rubocop-rails 4 | - rubocop-rspec 5 | 6 | inherit_mode: 7 | merge: 8 | - Exclude 9 | 10 | AllCops: 11 | NewCops: enable 12 | TargetRubyVersion: <%= RUBY_VERSION %> 13 | DisplayCopNames: true 14 | SuggestExtensions: false 15 | Exclude: 16 | - vendor/ruby/**/* 17 | - node_modules/**/* 18 | - .licenses/**/* 19 | Rails: 20 | Enabled: true 21 | Metrics/BlockLength: 22 | Exclude: 23 | - db/migrate/* 24 | - config/environments/* 25 | - lib/tasks/**/* 26 | - spec/**/* 27 | Style/Documentation: 28 | Enabled: false 29 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | PreCommit: 2 | AuthorName: 3 | enabled: false 4 | RuboCop: 5 | enabled: true 6 | on_warn: fail # Treat all warnings as failures 7 | TrailingWhitespace: 8 | enabled: true 9 | exclude: 10 | - '.licenses/**/*' 11 | 12 | PrePush: 13 | BundleAudit: 14 | enabled: true 15 | BundleOutdated: 16 | enabled: true 17 | 18 | PostCheckout: 19 | ALL: # Special hook name that customizes all hooks of this type 20 | quiet: true # Change all post-checkout hooks to only display output on failure 21 | IndexTags: 22 | enabled: true # Generate a tags file with `ctags` each time HEAD changes 23 | -------------------------------------------------------------------------------- /templates/overcommit.yml.erb: -------------------------------------------------------------------------------- 1 | PreCommit: 2 | AuthorName: 3 | enabled: false 4 | RuboCop: 5 | enabled: true 6 | on_warn: fail # Treat all warnings as failures 7 | TrailingWhitespace: 8 | enabled: true 9 | exclude: 10 | - '**/db/structure.sql' # Ignore trailing whitespace in generated files 11 | BundleAudit: 12 | enabled: true 13 | 14 | PrePush: 15 | Brakeman: 16 | enabled: true 17 | 18 | PostCheckout: 19 | ALL: # Special hook name that customizes all hooks of this type 20 | quiet: true # Change all post-checkout hooks to only display output on failure 21 | 22 | IndexTags: 23 | enabled: true # Generate a tags file with `ctags` each time HEAD changes 24 | -------------------------------------------------------------------------------- /lib/bankai/generators/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rails/generators' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class Base < Rails::Generators::Base 9 | include Bankai::Helper 10 | 11 | def self.default_source_root 12 | File.expand_path(File.join('..', '..', '..', 'templates'), __dir__) 13 | end 14 | 15 | private 16 | 17 | def app_name 18 | if Rails::VERSION::MAJOR >= 6 19 | Rails.app_class.module_parent_name.demodulize.underscore.dasherize 20 | else 21 | Rails.app_class.parent_name.demodulize.underscore.dasherize 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/bankai/generators/mailer_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class MailerGenerator < Base 9 | def configure_letter_opener 10 | inject_into_file( 11 | 'config/environments/development.rb', 12 | configuration, 13 | after: '# config.action_cable.disable_request_forgery_protection = true' 14 | ) 15 | end 16 | 17 | private 18 | 19 | def configuration 20 | <<-RUBY 21 | 22 | config.action_mailer.delivery_method = :letter_opener 23 | config.action_mailer.perform_deliveries = true 24 | RUBY 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /exe/bankai: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'pathname' 5 | 6 | source_path = File.expand_path("#{Pathname.new(__FILE__).dirname}../lib") 7 | $LOAD_PATH << source_path 8 | 9 | require 'bankai' 10 | 11 | if ARGV.empty? 12 | puts 'Please provide a path for the new application' 13 | puts 14 | puts 'See --help for more info' 15 | exit 0 16 | elsif ['-v', '--version'].include? ARGV[0] 17 | puts Bankai::VERSION 18 | exit 0 19 | end 20 | 21 | templates_root = File.expand_path( 22 | File.join('..', 'templates'), 23 | File.dirname(__FILE__) 24 | ) 25 | Bankai::Generator.source_root templates_root 26 | Bankai::Generator.source_paths << Rails::Generators::AppGenerator.source_root 27 | Bankai::Generator.source_paths << templates_root 28 | 29 | Bankai::Generator.start 30 | -------------------------------------------------------------------------------- /lib/bankai/generators/db_optimizations_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class DbOptimizationsGenerator < Base 9 | def configure_bullet 10 | inject_into_file( 11 | 'config/environments/development.rb', 12 | configuration, 13 | after: '# config.action_cable.disable_request_forgery_protection = true' 14 | ) 15 | end 16 | 17 | private 18 | 19 | def configuration 20 | <<-RUBY 21 | 22 | config.after_initialize do 23 | Bullet.enable = true 24 | Bullet.bullet_logger = true 25 | Bullet.rails_logger = true 26 | Bullet.add_footer = true 27 | end 28 | RUBY 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/bankai/generators/lint_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class LintGenerator < Base 9 | def configure_overcommit 10 | template 'overcommit.yml.erb', '.overcommit.yml' 11 | end 12 | 13 | def configure_rubocop 14 | template 'rubocop.yml.erb', '.rubocop.yml' 15 | end 16 | 17 | def install_overcommit 18 | execute_command :bundle, 'exec overcommit --install' 19 | end 20 | 21 | def rubocop_autocorrect 22 | execute_command :bundle, 'exec rubocop --auto-correct-all' 23 | end 24 | 25 | def rubocop_todo 26 | execute_command :bundle, 'exec rubocop --auto-gen-config' 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/bankai/generators/whenever_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class WheneverGenerator < Base 9 | def add_whenever 10 | gem 'whenever', require: false 11 | execute_command :bundle, 'exec rubocop -a Gemfile' 12 | execute_command :bundle, 'install' 13 | end 14 | 15 | def initialize_whenever 16 | execute_command :bundle, "exec wheneverize #{destination_root}" 17 | end 18 | 19 | def initialize_capistrano 20 | return unless capistrano? 21 | 22 | inject_into_file( 23 | 'Capfile', 24 | "require 'whenerver/capistrano'\n", 25 | after: "# require \"capistrano/passenger\"\n" 26 | ) 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /templates/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ENV.fetch('COVERAGE', false) || ENV.fetch('CI', false) 4 | require 'simplecov' 5 | require 'simplecov-cobertura' 6 | 7 | SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter if ENV.fetch('GITLAB_CI', false) 8 | SimpleCov.refuse_coverage_drop 9 | 10 | SimpleCov.start 'rails' do 11 | add_filter 'vendor' 12 | end 13 | end 14 | 15 | RSpec.configure do |config| 16 | config.expect_with :rspec do |expectations| 17 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 18 | end 19 | 20 | config.mock_with :rspec do |mocks| 21 | mocks.verify_partial_doubles = true 22 | end 23 | 24 | config.shared_context_metadata_behavior = :apply_to_host_groups 25 | 26 | config.expect_with :rspec do |c| 27 | c.syntax = :expect 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/bankai/generators/testing_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class TestingGenerator < Base 9 | def generate_rspec 10 | generate 'rspec:install' 11 | end 12 | 13 | def configure_rspec 14 | remove_file 'spec/rails_helper.rb' 15 | remove_file 'spec/spec_helper.rb' 16 | copy_file 'rails_helper.rb', 'spec/rails_helper.rb' 17 | copy_file 'spec_helper.rb', 'spec/spec_helper.rb' 18 | end 19 | 20 | def provide_shoulda_matchers_config 21 | copy_file( 22 | 'spec/shoulda_matchers.rb', 23 | 'spec/support/shoulda_matchers.rb' 24 | ) 25 | end 26 | 27 | def provide_database_rewinder_config 28 | copy_file( 29 | 'spec/database_rewinder.rb', 30 | 'spec/support/database_rewinder.rb' 31 | ) 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/bankai/generators/sitemap_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | HOST_TEMPLATE = <<-RUBY 8 | 9 | if Rails.env.production? 10 | "https://\#{ENV['APPLICATION_HOST']}" 11 | else 12 | "http://\#{ENV['APPLICATION_HOST']}" 13 | end 14 | RUBY 15 | 16 | # :nodoc: 17 | class SitemapGenerator < Base 18 | def add_sitemap_generator 19 | gem 'sitemap_generator' 20 | in_root { run 'bundle install' } 21 | end 22 | 23 | def init_sitemap 24 | in_root { run 'bundle exec rake sitemap:install' } 25 | end 26 | 27 | def generate_sitmap_config 28 | gsub_file 'config/sitemap.rb', 29 | %r{"http://www.example.com"}, 30 | HOST_TEMPLATE 31 | in_root do 32 | run 'bundle exec rubocop -a config/sitemap.rb' 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /templates/rails_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | ENV['RAILS_ENV'] ||= 'test' 5 | require File.expand_path('../config/environment', __dir__) 6 | 7 | abort('The Rails is running in production mode!') if Rails.env.production? 8 | require 'rspec/rails' 9 | 10 | require 'shoulda/matchers' 11 | require 'faker' 12 | require 'factory_bot' 13 | 14 | Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f } 15 | 16 | begin 17 | ActiveRecord::Migration.maintain_test_schema! 18 | rescue ActiveRecord::PendingMigrationError => e 19 | puts e.to_s.strip 20 | exit 1 21 | end 22 | RSpec.configure do |config| 23 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 24 | 25 | config.use_transactional_fixtures = false 26 | config.infer_spec_type_from_file_location! 27 | config.filter_rails_from_backtrace! 28 | 29 | config.include FactoryBot::Syntax::Methods 30 | # config.include Devise::Test::IntegrationHelpers, type: :request 31 | end 32 | -------------------------------------------------------------------------------- /lib/bankai/generators/deploy_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | module Bankai 6 | module Generators 7 | # :nodoc: 8 | class DeployGenerator < Base 9 | DEFAULT_REPO = 'git@example.com:me/my_repo.git' 10 | 11 | def install_capistrano 12 | execute_command :bundle, 'exec cap install' 13 | end 14 | 15 | def configure_capfile 16 | inject_into_file( 17 | 'Capfile', 18 | capistrano_plugins, 19 | after: "# require \"capistrano/passenger\"\n" 20 | ) 21 | end 22 | 23 | def replace_deploy_config 24 | template 'deploy.rb.erb', 'config/deploy.rb', force: true 25 | end 26 | 27 | protected 28 | 29 | def repo_url 30 | return DEFAULT_REPO unless Dir.exist?('.git') 31 | 32 | res = `git remote get-url origin` 33 | return DEFAULT_REPO if res.blank? 34 | 35 | res 36 | end 37 | 38 | private 39 | 40 | def capistrano_plugins 41 | plugins = [] 42 | plugins << 'require "capistrano/bundler"' 43 | plugins << 'require "capistrano/rails/assets"' unless options[:api] 44 | plugins << 'require "capistrano/rails/migrations"' 45 | plugins.join("\n") 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /templates/gitignore.erb: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | <% if sqlite3? -%> 11 | # Ignore the default SQLite database. 12 | /db/*.sqlite3 13 | /db/*.sqlite3-journal 14 | 15 | <% end -%> 16 | # Ignore all logfiles and tempfiles. 17 | /log/* 18 | /tmp/* 19 | <% if keeps? -%> 20 | !/log/.keep 21 | !/tmp/.keep 22 | <% end -%> 23 | *.orig 24 | .DS_Store 25 | 26 | <% unless skip_active_storage? -%> 27 | # Ignore uploaded files in development 28 | /storage/* 29 | <% if keeps? -%> 30 | !/storage/.keep 31 | <% end -%> 32 | <% end -%> 33 | 34 | <% unless options.skip_yarn? -%> 35 | /node_modules 36 | yarn-debug.log* 37 | yarn-error.log* 38 | .yarn-integrity 39 | 40 | <% end -%> 41 | <% unless options.api? -%> 42 | /public/assets 43 | <% end -%> 44 | .byebug_history 45 | 46 | <% unless options[:skip_rspec] -%> 47 | /coverage/ 48 | /spec/tmp 49 | <% end -%> 50 | 51 | # Dotenv 52 | .env 53 | .env* 54 | !.env.example 55 | 56 | # CarrierWave 57 | /public/uploads 58 | 59 | # Environment 60 | /.bundle 61 | /vendor/bundle 62 | -------------------------------------------------------------------------------- /templates/deploy.rb.erb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # config valid for current version and patch releases of Capistrano 4 | lock '~> <%= Bankai::CAPISTRANO_VERSION %>' 5 | 6 | set :application, '<%= app_name %>' 7 | set :repo_url, '<%= repo_url || 'git@example.com:me/my_repo.git' %>' 8 | 9 | # Default branch is :master 10 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp 11 | ask :branch, :master 12 | 13 | # Default deploy_to directory is /var/www/my_app_name 14 | set :deploy_to, '/srv/app' 15 | 16 | # Default value for :format is :airbrussh. 17 | # set :format, :airbrussh 18 | 19 | # You can configure the Airbrussh format using :format_options. 20 | # These are the defaults. 21 | # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto 22 | 23 | # Default value for :pty is false 24 | # set :pty, true 25 | 26 | # Default value for :linked_files is [] 27 | append :linked_files, 'config/database.yml', 'config/master.key' 28 | 29 | # Default value for linked_dirs is [] 30 | append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 31 | '.bundle', 'public/uploads', 'node_modules' 32 | 33 | # Default value for default_env is {} 34 | set :default_env, { path: '/usr/local/ruby-<%= RUBY_VERSION %>/bin:$PATH' } 35 | 36 | # Default value for local_user is ENV['USER'] 37 | # set :local_user, -> { `git config user.name`.chomp } 38 | 39 | # Default value for keep_releases is 5 40 | # set :keep_releases, 5 41 | 42 | # Uncomment the following to require manually verifying the host key before first deploy. 43 | # set :ssh_options, verify_host_key: :secure 44 | -------------------------------------------------------------------------------- /bankai.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'bankai/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.required_ruby_version = ">= #{Bankai::RUBY_VERSION}" 9 | spec.name = 'bankai' 10 | spec.version = Bankai::VERSION 11 | spec.authors = %w[5xRuby 蒼時弦也] 12 | spec.email = ['hi@5xruby.tw', 'contact0@frost.tw'] 13 | 14 | spec.summary = 'The Rails template for 5xRuby' 15 | spec.description = 'The tool to generate Rails template for 5xRuby' 16 | spec.homepage = 'https://github.com/5xRuby/bankai' 17 | 18 | # Specify which files should be added to the gem when it is released. 19 | # The `git ls-files -z` loads the files in the 20 | # RubyGem that have been added into git. 21 | spec.files = Dir.chdir(File.expand_path(__dir__)) do 22 | `git ls-files -z` 23 | .split("\x0") 24 | .reject { |f| f.match(%r{^(test|spec|features)/}) } 25 | end 26 | spec.bindir = 'exe' 27 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 28 | spec.require_paths = ['lib'] 29 | 30 | spec.add_development_dependency 'bundler-audit' 31 | spec.add_development_dependency 'overcommit' 32 | spec.add_development_dependency 'rake', '~> 12.0' 33 | spec.add_development_dependency 'rspec', '~> 3.0' 34 | spec.add_development_dependency 'rspec_junit_formatter' 35 | spec.add_development_dependency 'rubocop', '~> 1.8.1' 36 | spec.add_development_dependency 'simplecov', '~> 0.17.1' 37 | 38 | # TODO: Allow specify rails version 39 | spec.add_dependency 'rails', ">= #{Bankai::RAILS_VERSION}" 40 | end 41 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: ruby:2.7.4 2 | 3 | stages: 4 | - lint 5 | - test 6 | - analysis 7 | 8 | cache: 9 | paths: 10 | - vendor/ruby 11 | 12 | .install_ruby_gems: &install_ruby_gems 13 | - gem install bundler -v 2.2.26 14 | - bundle install --path vendor 15 | 16 | before_script: 17 | - *install_ruby_gems 18 | 19 | rubocop: 20 | stage: lint 21 | script: 22 | - bundle exec rubocop --format progress --format json --out rubocop.json 23 | artifacts: 24 | paths: 25 | - rubocop.json 26 | except: 27 | - schedules 28 | 29 | bundler-audit: 30 | stage: lint 31 | before_script: 32 | - *install_ruby_gems 33 | - gem install bundler-audit 34 | - bundle audit --update 35 | script: 36 | - bundle audit 37 | allow_failure: true 38 | 39 | rspec: 40 | stage: test 41 | script: 42 | - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml 43 | artifacts: 44 | paths: 45 | - rspec.xml 46 | - coverage 47 | reports: 48 | junit: rspec.xml 49 | except: 50 | - schedules 51 | 52 | sonarqube: 53 | stage: analysis 54 | image: 55 | name: sonarsource/sonar-scanner-cli 56 | entrypoint: [""] 57 | variables: 58 | GIT_DEPTH: 0 59 | before_script: [] 60 | script: 61 | - sonar-scanner 62 | -Dsonar.projectKey=Bankai 63 | -Dsonar.sourceEncoding=UTF-8 64 | -Dsonar.qualitygate.wait=true 65 | -Dsonar.ruby.rubocop.reportPaths=rubocop.json 66 | -Dsonar.ruby.coverage.reportPaths=coverage/.resultset.json 67 | -Dsonar.exclusions=vendor/ruby/**/* 68 | -Dsonar.coverage.exclusions=spec/**/* 69 | -Dsonar.projectVersion=$CI_COMMIT_SHORT_SHA 70 | -Dsonar.sources=. 71 | allow_failure: true 72 | only: 73 | - master 74 | -------------------------------------------------------------------------------- /lib/bankai/builder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Bankai 4 | # :nodoc: 5 | class Builder < Rails::AppBuilder 6 | def readme 7 | template 'README.md.erb', 'README.md' 8 | end 9 | 10 | def gitignore 11 | template 'gitignore.erb', '.gitignore' 12 | end 13 | 14 | def gemfile 15 | template 'Gemfile.erb', 'Gemfile' 16 | end 17 | 18 | def replace_gemfile(path) 19 | template 'Gemfile.erb', 'Gemfile', force: true do |content| 20 | if path 21 | content.gsub(/gem .bankai./) { |s| %(#{s}, path: "#{path}") } 22 | else 23 | content 24 | end 25 | end 26 | end 27 | 28 | def configure_puma_dev 29 | application(nil, env: 'development') do 30 | "config.hosts << '.test'" 31 | end 32 | end 33 | 34 | def configure_quiet_assets 35 | return if options[:api] 36 | 37 | application do 38 | 'config.assets.quiet = true' 39 | end 40 | end 41 | 42 | # rubocop:disable Metrics/MethodLength 43 | def configure_generators 44 | application do 45 | <<-RUBY 46 | config.generators do |generate| 47 | generate.helper false 48 | generate.javascripts false 49 | generate.request_specs false 50 | generate.routing_specs false 51 | generate.stylesheets false 52 | generate.test_framework :rspec 53 | generate.view_specs false 54 | end 55 | RUBY 56 | end 57 | end 58 | 59 | def setup_default_directories 60 | [ 61 | 'spec/lib', 62 | 'spec/controllers', 63 | 'spec/helpers', 64 | 'spec/support/matchers', 65 | 'spec/support/mixins', 66 | 'spec/support/shared_examples' 67 | ].each do |dir| 68 | empty_directory_with_keep_file dir 69 | end 70 | end 71 | # rubocop:enable Metrics/MethodLength 72 | 73 | def clear_seed_file 74 | File.write("#{destination_root}/db/seeds.rb", '') 75 | end 76 | 77 | def setup_rack_mini_profiler 78 | copy_file( 79 | 'rack_mini_profiler.rb', 80 | 'config/initializers/rack_mini_profiler.rb' 81 | ) 82 | end 83 | 84 | def copy_dotfiles 85 | directory('dotfiles', '.') 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Bankai 2 | === 3 | 4 | This gem is inspired by [Suspenders](https://github.com/thoughtbot/suspenders) for [5xRuby](https://5xruby.tw) to bootstrap a rails project. 5 | 6 | ## Installation 7 | 8 | First, install bankai 9 | 10 | ``` 11 | gem install bankai 12 | ``` 13 | 14 | The bootstrap your rails project 15 | 16 | ``` 17 | bankai projectname 18 | ``` 19 | 20 | ## Requirement 21 | 22 | * `~> 0.13` required `rails >= 7.0` 23 | * `<= 0.12` required `rails >= 5.2` 24 | 25 | ## Gemfile 26 | 27 | * [Oj](http://www.ohler.com/oj/) 28 | 29 | ### Development 30 | 31 | * [Brakeman](https://github.com/presidentbeef/brakeman) 32 | * [Bundler Audit](https://github.com/rubysec/bundler-audit) 33 | * [Rubocop](https://github.com/bbatsov/rubocop) 34 | * [Rack Mini Profiler](https://github.com/MiniProfiler/rack-mini-profiler) - Enable with `RACK_MINI_PROFILER=1` 35 | * [Annotate](https://github.com/ctran/annotate_models) 36 | * [Bullet](https://github.com/flyerhzm/bullet) 37 | * [Dotenv](https://github.com/bkeepers/dotenv) 38 | * [Letter Opener](https://github.com/ryanb/letter_opener) 39 | * [Overcommit](https://github.com/brigade/overcommit) 40 | * [Pry Rails](https://github.com/rweng/pry-rails) 41 | 42 | ### Test 43 | 44 | * [Capybara](https://github.com/jnicklas/capybara) 45 | * [Google Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/home) 46 | * [Factory Bot](https://github.com/thoughtbot/factory_bot) 47 | * [Faker](https://github.com/stympy/faker) 48 | * [Rspec](https://github.com/rspec/rspec) 49 | * [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) 50 | * [Simplecov](https://github.com/colszowka/simplecov) - Enable with `COVERAGE=1` 51 | 52 | ## Others 53 | 54 | * Configured `.gitlab-ci.yml` 55 | * Auto filled capistrano configure 56 | 57 | ## Development 58 | 59 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 60 | 61 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 62 | 63 | ### Test Gem 64 | 65 | If you want to test the changes for generator is works well, you can add `--path` options to use your local version 66 | 67 | ``` 68 | bankai projectname --path=YOUR_LOCAL_GEM_PATH 69 | ``` 70 | 71 | ## Contributing 72 | 73 | Bug reports and pull requests are welcome on GitHub at https://github.com/5xRuby/bankai. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 74 | 75 | ## Code of Conduct 76 | 77 | Everyone interacting in the Bankai project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/5xRuby/bankai/blob/master/CODE_OF_CONDUCT.md). 78 | -------------------------------------------------------------------------------- /lib/bankai/generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rails/generators' 4 | require 'rails/generators/rails/app/app_generator' 5 | 6 | module Bankai 7 | # :nodoc: 8 | class Generator < Rails::Generators::AppGenerator 9 | hide! 10 | 11 | class_option :database, type: :string, aliases: '-d', default: 'postgresql', 12 | desc: 'Configure for selected database ' \ 13 | "(options: #{Rails::Generators::Database::DATABASES.join('/')})" 14 | 15 | class_option :capistrano, type: :boolean, default: false, 16 | desc: 'Use Capistrano' 17 | 18 | class_option :skip_test, type: :boolean, default: true, 19 | desc: 'Skip test files' 20 | 21 | class_option :skip_coffee, type: :boolean, default: true, 22 | desc: "Don't use CoffeeScript" 23 | 24 | class_option :skip_rspec, type: :boolean, default: false, 25 | desc: 'Skip rspec files' 26 | 27 | class_option :path, type: :string, default: nil, 28 | desc: 'Path to the gem' 29 | 30 | def finish_template 31 | invoke :customization 32 | super 33 | end 34 | 35 | def customization 36 | invoke :customize_gemfile 37 | invoke :setup_development_environment 38 | invoke :configure_app 39 | invoke :setup_dotfiles 40 | invoke :generate_default 41 | invoke :setup_default_directories 42 | end 43 | 44 | def customize_gemfile 45 | build :replace_gemfile, options[:path] 46 | bundle_command 'install' 47 | end 48 | 49 | def setup_development_environment 50 | say 'Setting up the development environment' 51 | build :configure_quiet_assets 52 | build :configure_puma_dev 53 | build :configure_generators 54 | build :clear_seed_file 55 | # TODO: Add setup script 56 | end 57 | 58 | def configure_app 59 | say 'Configuring app' 60 | # TODO: Configure ActionMailer 61 | build :setup_rack_mini_profiler 62 | end 63 | 64 | def setup_dotfiles 65 | build :copy_dotfiles 66 | end 67 | 68 | def generate_default 69 | run('spring stop') 70 | generate('bankai:testing') unless options[:skip_rspec] 71 | generate('bankai:ci', options.api? ? '--api' : '') 72 | generate('bankai:json') 73 | generate('bankai:db_optimizations') 74 | generate('bankai:mailer') 75 | generate('bankai:deploy') if options[:capistrano] 76 | generate('annotate:install') 77 | generate('bankai:lint') 78 | end 79 | 80 | def setup_default_directories 81 | build :setup_default_directories 82 | end 83 | 84 | def depends_on_system_test? 85 | !(options[:skip_system_test] || options[:skip_rspec] || options[:api]) 86 | end 87 | 88 | def self.banner 89 | "bankai #{arguments.map(&:usage).join(' ')} [options]" 90 | end 91 | 92 | protected 93 | 94 | # rubocop:disable Naming/AccessorMethodName 95 | def get_builder_class 96 | Bankai::Builder 97 | end 98 | # rubocop:enable Naming/AccessorMethodName 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at elct9620@frost.tw. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /templates/Gemfile.erb: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | ruby '<%= RUBY_VERSION -%>' 5 | 6 | <% gemfile_entries.each do |gemfile_entry| %> 7 | <%= gemfile_entry %> 8 | <% end -%> 9 | <% unless options.minimal? -%> 10 | 11 | # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] 12 | # gem "kredis" 13 | 14 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 15 | # gem "bcrypt", "~> 3.1.7" 16 | <% end -%> 17 | 18 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 19 | gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] 20 | <% if depend_on_bootsnap? -%> 21 | 22 | # Reduces boot times through caching; required in config/boot.rb 23 | gem "bootsnap", require: false 24 | <% end -%> 25 | <% unless skip_sprockets? || options.minimal? -%> 26 | 27 | # Use Sass to process CSS 28 | # gem "sassc-rails" 29 | <% end -%> 30 | <% unless skip_active_storage? -%> 31 | 32 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 33 | # gem "image_processing", "~> 1.2" 34 | <% end -%> 35 | <%- if options.api? -%> 36 | 37 | # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible 38 | # gem "rack-cors" 39 | <%- end -%> 40 | <% if RUBY_ENGINE == "ruby" -%> 41 | 42 | group :development, :test do 43 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 44 | gem "debug", platforms: %i[ mri mingw x64_mingw ] 45 | 46 | gem 'brakeman', require: false 47 | gem 'bundler-audit', require: false 48 | gem 'rubocop', '~> <%= Bankai::RUBOCOP_VERSION %>', require: false 49 | gem 'rubocop-performance', require: false 50 | gem 'rubocop-rails', require: false 51 | gem 'rubocop-rspec', require: false 52 | 53 | <%- unless options[:skip_rspec] -%> 54 | gem 'database_rewinder' 55 | gem 'factory_bot_rails' 56 | gem 'faker' 57 | gem 'rspec', require: false 58 | gem 'rspec-rails', require: false 59 | gem 'shoulda-matchers', require: false 60 | gem 'simplecov', require: false 61 | gem 'simplecov-cobertura', require: false 62 | <%- end -%> 63 | 64 | gem 'bankai' 65 | end 66 | <% end -%> 67 | 68 | group :development do 69 | <%- unless options.api? || options.skip_dev_gems? -%> 70 | # Use console on exceptions pages [https://github.com/rails/web-console] 71 | gem "web-console" 72 | 73 | # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] 74 | # gem "rack-mini-profiler" 75 | 76 | <%- end -%> 77 | # Speed up commands on slow machines / big apps [https://github.com/rails/spring] 78 | # gem "spring" 79 | 80 | <% if options[:capistrano] -%> 81 | gem 'capistrano', '<%= Bankai::CAPISTRANO_VERSION %>' 82 | gem 'capistrano-bundler' 83 | gem 'capistrano-rails' 84 | # gem 'capistrano-sidekiq' 85 | # gem 'capistrano-passenger' 86 | <% end -%> 87 | 88 | gem 'annotate' 89 | gem 'bullet' 90 | gem 'dotenv-rails' 91 | gem 'letter_opener' 92 | gem 'overcommit', require: false 93 | gem 'pry-rails' 94 | gem 'rack-mini-profiler', require: false 95 | end 96 | 97 | <%- if depends_on_system_test? -%> 98 | group :test do 99 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 100 | gem "capybara" 101 | gem "selenium-webdriver" 102 | gem "webdrivers" 103 | end 104 | <%- end -%> 105 | -------------------------------------------------------------------------------- /templates/gitlab-ci.yml.erb: -------------------------------------------------------------------------------- 1 | default: 2 | image: ruby:<%= RUBY_VERSION %> 3 | 4 | stages: 5 | - lint 6 | - test 7 | - deploy 8 | 9 | variables: 10 | RAILS_ENV: test 11 | <%- unless options.api? -%> 12 | NODE_VERSION: 12.13.1 13 | <%- end -%> 14 | BUNDLER_VERSION: 2.2.26 15 | <%- if pg? -%> 16 | POSTGRES_DB: <%= app_name %> 17 | POSTGRES_PASSWORD: postgres 18 | DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/$POSTGRES_DB" 19 | <%- end -%> 20 | <%- if mysql? -%> 21 | MYSQL_DATABASE: <%= app_name %> 22 | MYSQL_USER: <%= app_name %> 23 | MYSQL_PASSWORD: <%= app_name %> 24 | MYSQL_RANDOM_ROOT_PASSWORD: "true" 25 | DATABASE_URL: "mysql2://$MYSQL_USER:$MYSQL_PASSWORD@mysql:3306/$MYSQL_DATABASE" 26 | <%- end -%> 27 | 28 | .install_ruby_gems: &install_ruby_gems 29 | - gem install bundler -v ${BUNDLER_VERSION} 30 | - bundle install --path vendor 31 | <% unless options.api? %> 32 | .install_nodejs: &install_nodejs 33 | - curl -SLO https://nodejs.org/dist/v$NODE_VERSION/node-v${NODE_VERSION}-linux-x64.tar.xz && tar -xJf node-v${NODE_VERSION}-linux-x64.tar.xz -C /usr/local --strip-components=1; 34 | - curl -o- -L https://yarnpkg.com/install.sh | bash 35 | - export PATH=$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH 36 | <% end -%> 37 | 38 | .common: 39 | before_script: 40 | - export LANG=C.UTF-8 41 | - export LC_ALL=C.UTF-8 42 | - *install_ruby_gems 43 | cache: 44 | key: 45 | files: 46 | - Gemfile.lock 47 | <%- unless options.api? -%> 48 | - yarn.lock 49 | <%- end -%> 50 | paths: 51 | - vendor/ruby 52 | <% unless options.api? %> 53 | - node_modules 54 | <% end -%> 55 | 56 | rubocop: 57 | extends: .common 58 | stage: lint 59 | script: 60 | - bundle exec rubocop 61 | rules: 62 | - if: $CI_MERGE_REQUEST_ID 63 | 64 | brakeman: 65 | image: registry.gitlab.com/gitlab-org/security-products/analyzers/brakeman:2 66 | stage: lint 67 | allow_failure: true 68 | script: 69 | - /analyzer run 70 | artifacts: 71 | reports: 72 | sast: gl-sast-report.json 73 | rules: 74 | - if: $CI_MERGE_REQUEST_ID 75 | 76 | bundler-audit: 77 | extends: .common 78 | stage: lint 79 | script: 80 | - gem install bundler-audit 81 | - bundle audit --update 82 | - bundle audit 83 | rules: 84 | - if: $CI_MERGE_REQUEST_ID 85 | - if: $CI_PIPELINE_SOURCE == 'schedule' 86 | allow_failure: true 87 | 88 | bundler-leak: 89 | extends: .common 90 | stage: lint 91 | script: 92 | - gem install bundler-leak 93 | - bundle leak check --update 94 | - bundle leak 95 | rules: 96 | - if: $CI_MERGE_REQUEST_ID 97 | - if: $CI_PIPELINE_SOURCE == 'schedule' 98 | <% unless options.api? %> 99 | yarn-audit: 100 | extends: .common 101 | stage: lint 102 | before_script: 103 | - *install_nodejs 104 | script: 105 | - yarn audit 106 | rules: 107 | - if: $CI_MERGE_REQUEST_ID 108 | - if: $CI_PIPELINE_SOURCE == 'schedule' 109 | allow_failure: true 110 | <% end -%> 111 | 112 | rspec: 113 | extends: .common 114 | stage: test 115 | before_script: 116 | - *install_ruby_gems 117 | <%- unless options.api? -%> 118 | - *install_nodejs 119 | - yarn install 120 | <%- end -%> 121 | services: 122 | <%- if pg? -%> 123 | - postgres:12-alpine 124 | <%- end -%> 125 | <%- if mysql? -%> 126 | - name: mysql:5.7 127 | command: ['mysqld', '--character-set-server=utf8', '--collation-server=utf8_unicode_ci'] 128 | <%- end -%> 129 | script: 130 | - bundle exec rake db:migrate 131 | - bundle exec rspec 132 | rules: 133 | - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH 134 | - if: $CI_MERGE_REQUEST_ID 135 | artifacts: 136 | reports: 137 | coverage_report: 138 | coverage_format: cobertura 139 | path: coverage/coverage.xml 140 | -------------------------------------------------------------------------------- /templates/README.md.erb: -------------------------------------------------------------------------------- 1 | <%= app_name.humanize %> 2 | === 3 | 4 | ## 系統需求 5 | 6 | * Ruby <%= RUBY_VERSION %> 7 | <%- case options[:database] -%> 8 | <%- when 'postgresql' then -%>* PostgreSQL 9.6+ 9 | <%- when 'mysql' then -%>* MySQL 5.7+ 10 | <%- end -%> 11 | * Node.js 8.0 (以上) 12 | 13 | ## 環境設定 14 | 15 | 以下的設定皆以 macOS 為主。 16 | 17 | ### Homebrew 18 | 19 | 在 macOS 需要有 [Homebrew](https://brew.sh/index_zh-tw) 來輔助安裝環境。 20 | 21 | ```bash 22 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 23 | ``` 24 | 25 | 執行完畢後可以透過 `brew doctor` 確認是否可用。 26 | 27 | ### Ruby 28 | 29 | 為了配合多個版本的環境,建議使用 `rbenv` 或者 `rvm` 來管理 Ruby 環境。 30 | 31 | ```bash 32 | # 選用 rbenv 33 | brew install rbenv 34 | 35 | # 選用 rvm 36 | brew install rvm 37 | ``` 38 | 39 | 完成後請參考終端機顯示的訊息設定 `.bashrc` 或者其他 Shell 設定檔。 40 | 41 | ```bash 42 | # 選用 rbenv 43 | rbenv install <%= RUBY_VERSION %> 44 | 45 | # 選用 rvm 46 | rvm install <%= RUBY_VERSION %> 47 | ``` 48 | 49 | 完成後需要先將 Bundler 安裝到新安裝的 Ruby 環境中(rvm 可能會先預裝完畢) 50 | 51 | ```bash 52 | # 先確認是否在正確的 Ruby 版本執行 53 | ruby -v 54 | # => ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin17] 55 | 56 | gem install bundler 57 | ``` 58 | <%- case options[:database] -%> 59 | <%- when 'postgresql' -%> 60 | ### PostgreSQL 61 | 62 | 請注意不要直接輸入 `postgresql` 否則會安裝到最新版的 PostgreSQL 63 | 64 | ```bash 65 | # 安裝 66 | brew install postgresql@9.6 67 | 68 | # 啟動伺服器 69 | brew services start postgresql@9.6 70 | ``` 71 | 72 | <%- when 'mysql' -%> 73 | ### MySQL 74 | 75 | 請注意不要直接輸入 `mysql` 否則會安裝到最新版的 MySQL 76 | 77 | ```bash 78 | # 安裝 79 | brew install mysql@5.7 80 | 81 | # 啟動伺服器 82 | brew services start mysql@5.7 83 | ``` 84 | 85 | 啟動之前請參考終端機顯示的安裝訊息來初始化 MySQL 資料庫 86 | 87 | <%- end -%> 88 | ### Node.js 89 | 90 | Rails 需要 JavaScript Runtime 一般會使用 Node.js。 91 | 92 | ```bash 93 | brew install node 94 | ``` 95 | 96 | Webpacker 使用 Yarn 管理安裝的 JavaScript 套件,我們還需要將 Yarn 安裝進來。 97 | 98 | ```bash 99 | brew install yarn 100 | ``` 101 | 102 | ### Rails 103 | 104 | 請先透過 git 將專案下載到本地端。 105 | 106 | ```bash 107 | # 切換到專案目錄 108 | cd <%= app_name %> 109 | 110 | # 安裝 Rails 所需套件 111 | bundle install 112 | 113 | # 設定 git hook 114 | bundle exec overcommit --install 115 | ``` 116 | 117 | Overcommit 會做以下檢查: 118 | 119 | 1. commit 前:使用 rubocop 檢查語法 120 | 2. push 前:使用 brakeman 檢查安全性問題 121 | 122 | ```bash 123 | # 設定資料庫 124 | bundle exec rake db:create 125 | 126 | # 更新資料庫到最新版 127 | bundle exec rake db:migrate 128 | ``` 129 | 130 | <%- if options[:database] == 'mysql' -%> 131 | #### 執行 bundle install 時 mysql2 gem 安裝失敗 132 | 133 | 這可能是因為我們指定了 MySQL 版本,但是作業系統裡面並不知道有 MySQL 的存在,造成自動安裝失敗。 134 | 我們可以透過以下指令手動安裝: 135 | 136 | ``` 137 | # 0.5.2 是目前的版本,之後有更新情參考錯誤訊息指示的版本 138 | export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix openssl)/lib 139 | gem install mysql2 -v 0.5.2 -- --with-mysql-config=$(brew --prefix mysql@5.7)/bin/mysql_config 140 | ``` 141 | 142 | <%- end -%> 143 | ## 執行專案 144 | 145 | ### Rails 伺服器 146 | 147 | ```bash 148 | # 這是 rails server 的縮寫 149 | rails s 150 | ``` 151 | 152 | 開啟後預設可以透過 `http://localhost:3000` 看到網站 153 | 154 | #### PendingMigration 錯誤 155 | 156 | 這是因為最新版本的資料庫已經被更改,但是本機的資料庫還沒有被更新。 157 | 158 | ```bash 159 | bundle exec rake db:migrate 160 | ``` 161 | 162 | 執行 `db:migrate` 指令更新資料庫即可。 163 | 164 | <%- if options[:webpack] -%> 165 | ### Webpack 伺服器 166 | 167 | 因為專案使用了 Webpacker 所以需要開啟 Webpack 伺服器來轉換 JavaScript 168 | 169 | ```bash 170 | ./bin/webpack-dev-server 171 | ``` 172 | 173 | 和 Rails 伺服器同時打開後,就可以看到正常的網站畫面 174 | 175 | <%- end -%> 176 | <%- unless options[:skip_rspec] -%> 177 | ### 運行測試 178 | 179 | 這個專案使用 RSpec 進行測試,可以透過執行以下指令運行 180 | 181 | ```bash 182 | bundle exec rspec 183 | ``` 184 | 185 | <%- end -%> 186 | ### Ruby 語法檢查 187 | 188 | 這個功能會在 commit 前自動執行,必要時可以手動進行 189 | 190 | ```bash 191 | bundle exec rubocop 192 | ``` 193 | 194 | ### Ruby 安全性檢查 195 | 196 | 這個功能會在 push 前自動執行,必要時可以手動進行 197 | 198 | ```bash 199 | bundle exec brakeman 200 | ``` 201 | 202 | ### 建立 .env 檔案 203 | 204 | 建立 `.env` 檔案,並依據 local 開發環境需求修改設定內容。 205 | 206 | ```bash 207 | cp .env.example .env 208 | ``` 209 | 210 | <%- if options[:capistrano] -%> 211 | ## 部署 212 | 213 | 這個專案使用 Capistrano 進行部署,請先確定有權限透過 `deployer` 帳號 SSH 到伺服器上。 214 | 215 | ```bash 216 | cap [ENV] deploy 217 | ``` 218 | 219 | 假設要部署到測試(Staging)環境,請使用以下指令 220 | 221 | ```bash 222 | cap staging deploy 223 | ``` 224 | 225 | 如果是正式環境,則使用以下指令 226 | 227 | ```bash 228 | cap production deploy 229 | ``` 230 | 231 | 過程中會詢問要使用的 Git Branch,預設為 master branch,如果需要測試某個 Git Branch 請先將他上傳到 GitHub 上,並且和團隊成員確認後手動輸入 branch 再進行部署跟測試。 232 | <%- end -%> 233 | --------------------------------------------------------------------------------