schienenzeppelin 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +17 -0
  3. data/.github/workflows/outdated.yml +20 -0
  4. data/.gitignore +282 -0
  5. data/.rspec_status +3 -0
  6. data/.rubocop.yml +28 -0
  7. data/.tool-versions +1 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/GALLERY.md +29 -0
  10. data/Gemfile +13 -0
  11. data/Gemfile.lock +184 -0
  12. data/LICENSE +21 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +174 -0
  15. data/Rakefile +12 -0
  16. data/TODO.md +32 -0
  17. data/bin/console +15 -0
  18. data/bin/setup +8 -0
  19. data/exe/sz +25 -0
  20. data/images/create.png +0 -0
  21. data/images/error.png +0 -0
  22. data/images/home.png +0 -0
  23. data/images/index.png +0 -0
  24. data/images/login.png +0 -0
  25. data/images/mobile.png +0 -0
  26. data/lib/schienenzeppelin.rb +18 -0
  27. data/lib/schienenzeppelin/app_builder.rb +88 -0
  28. data/lib/schienenzeppelin/app_generator.rb +95 -0
  29. data/lib/schienenzeppelin/helper_base.rb +28 -0
  30. data/lib/schienenzeppelin/helpers/annotate.rb +11 -0
  31. data/lib/schienenzeppelin/helpers/capistrano.rb +35 -0
  32. data/lib/schienenzeppelin/helpers/continuous_integration.rb +12 -0
  33. data/lib/schienenzeppelin/helpers/credentials.rb +49 -0
  34. data/lib/schienenzeppelin/helpers/devise.rb +45 -0
  35. data/lib/schienenzeppelin/helpers/errors.rb +67 -0
  36. data/lib/schienenzeppelin/helpers/factory_bot.rb +13 -0
  37. data/lib/schienenzeppelin/helpers/generators.rb +26 -0
  38. data/lib/schienenzeppelin/helpers/high_voltage.rb +11 -0
  39. data/lib/schienenzeppelin/helpers/home.rb +17 -0
  40. data/lib/schienenzeppelin/helpers/hotwire.rb +11 -0
  41. data/lib/schienenzeppelin/helpers/pundit.rb +12 -0
  42. data/lib/schienenzeppelin/helpers/rspec.rb +13 -0
  43. data/lib/schienenzeppelin/helpers/rubocop.rb +11 -0
  44. data/lib/schienenzeppelin/helpers/scaffold.rb +11 -0
  45. data/lib/schienenzeppelin/helpers/services.rb +11 -0
  46. data/lib/schienenzeppelin/helpers/sidekiq.rb +13 -0
  47. data/lib/schienenzeppelin/helpers/stimulus.rb +11 -0
  48. data/lib/schienenzeppelin/helpers/stimulus_components.rb +29 -0
  49. data/lib/schienenzeppelin/helpers/tailwind.rb +18 -0
  50. data/lib/schienenzeppelin/version.rb +7 -0
  51. data/schienenzeppelin.gemspec +37 -0
  52. data/schienenzeppelin.jpg +0 -0
  53. data/script.md +104 -0
  54. data/templates/.dockerignore.erb +51 -0
  55. data/templates/.entrypoint.sh.erb +16 -0
  56. data/templates/.env.development.erb +3 -0
  57. data/templates/.foreman.erb +1 -0
  58. data/templates/.github/workflows/build.yml.erb +49 -0
  59. data/templates/.gitignore.erb +285 -0
  60. data/templates/.irbrc.erb +12 -0
  61. data/templates/.rubocop.yml.erb +37 -0
  62. data/templates/.tool-versions.erb +1 -0
  63. data/templates/Capfile.erb +24 -0
  64. data/templates/Dockerfile.erb +45 -0
  65. data/templates/Gemfile.erb +122 -0
  66. data/templates/Procfile.dev.erb +6 -0
  67. data/templates/Procfile.erb +2 -0
  68. data/templates/README.md.erb +43 -0
  69. data/templates/app/controllers/authorized_controller.rb.erb +10 -0
  70. data/templates/app/controllers/errors_controller.rb.erb +24 -0
  71. data/templates/app/javascript/images/checkmark.svg +1 -0
  72. data/templates/app/javascript/images/logo.svg +1 -0
  73. data/templates/app/javascript/stylesheets/components.scss +206 -0
  74. data/templates/app/policies/application_policy.rb +55 -0
  75. data/templates/app/services/application_service.rb +14 -0
  76. data/templates/app/views/devise/confirmations/new.html.erb +24 -0
  77. data/templates/app/views/devise/passwords/edit.html.erb +34 -0
  78. data/templates/app/views/devise/passwords/new.html.erb +23 -0
  79. data/templates/app/views/devise/registrations/edit.html.erb +62 -0
  80. data/templates/app/views/devise/registrations/new.html.erb +45 -0
  81. data/templates/app/views/devise/sessions/new.html.erb +33 -0
  82. data/templates/app/views/devise/shared/_error_messages.html.erb +15 -0
  83. data/templates/app/views/devise/shared/_form_wrap.html.erb +5 -0
  84. data/templates/app/views/devise/shared/_links.html.erb +25 -0
  85. data/templates/app/views/devise/unlocks/new.html.erb +22 -0
  86. data/templates/app/views/errors/internal_error.html.erb +14 -0
  87. data/templates/app/views/errors/not_found.html.erb +14 -0
  88. data/templates/app/views/errors/unacceptable.html.erb +14 -0
  89. data/templates/app/views/layouts/application.html.erb.tt +30 -0
  90. data/templates/app/views/pages/home.html.erb.tt +20 -0
  91. data/templates/app/views/shared/_flashes.html.erb.tt +12 -0
  92. data/templates/app/views/shared/_footer.html.erb.tt +21 -0
  93. data/templates/app/views/shared/_navbar.html.erb.tt +40 -0
  94. data/templates/bin/setup.erb +146 -0
  95. data/templates/config/credentials.yml.erb +7 -0
  96. data/templates/config/initializers/high_voltage.rb +6 -0
  97. data/templates/config/initializers/lograge.rb +5 -0
  98. data/templates/config/initializers/sidekiq.rb +10 -0
  99. data/templates/config/postgresql.yml.erb +23 -0
  100. data/templates/docker-compose.yml.erb +21 -0
  101. data/templates/lib/capistrano/tasks/seeds.rake +12 -0
  102. data/templates/lib/capistrano/tasks/sidekiq.rake +36 -0
  103. data/templates/lib/generators/rails/navigation/USAGE +6 -0
  104. data/templates/lib/generators/rails/navigation/navigation_generator.rb +15 -0
  105. data/templates/lib/generators/rails/scaffold_controller_generator.rb +12 -0
  106. data/templates/lib/tasks/auto_annotate_models.rake +58 -0
  107. data/templates/lib/templates/erb/scaffold/_form.html.erb +39 -0
  108. data/templates/lib/templates/erb/scaffold/edit.html.erb +7 -0
  109. data/templates/lib/templates/erb/scaffold/index.html.erb +34 -0
  110. data/templates/lib/templates/erb/scaffold/new.html.erb +7 -0
  111. data/templates/lib/templates/erb/scaffold/show.html.erb +18 -0
  112. data/templates/public/500.html.erb +26 -0
  113. data/templates/spec/rails_helper.rb +26 -0
  114. data/templates/spec/spec_helper.rb +61 -0
  115. data/templates/spec/support/factory_bot.rb +5 -0
  116. data/templates/spec/support/shoulda_matchers.rb +8 -0
  117. metadata +179 -0
data/Rakefile ADDED
@@ -0,0 +1,12 @@
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
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/TODO.md ADDED
@@ -0,0 +1,32 @@
1
+
2
+ # TODO
3
+
4
+ ## Phase 2
5
+ - Schienenzeppelin Repo CI (notify gem releases, tests)
6
+ - Loads of testing
7
+ - Hide generators and scaffolds in sz gem, don't copy as templates. See JB, use railtie
8
+
9
+ ## Phase 3
10
+ - Make everything skippable, manage dependencies between items
11
+ - Take advantage of saved config (as rails new does)
12
+ - Licensing?
13
+ - Homepage & Newsletter
14
+ - Goodies for Business:
15
+ - Admin pages
16
+ - Social Logins
17
+ - Cloud Storage ?
18
+ - Payments
19
+ - Monitoring (Skylight, ...)
20
+ - Email Providers (Mailgun, ...)
21
+ - Reporting (Bugsnag, ...)
22
+ - Dockerfile
23
+ - https://dev.to/citronak/modern-rails-flash-messages-part-1-viewcomponent-stimulus-tailwind-css-3alm
24
+ - Configuration wizard via command line
25
+ - Alternative configurations:
26
+ - Differernt DB
27
+ - Different BG Jobs
28
+ - Different Deployment
29
+
30
+ - Additional Gems:
31
+ - Pagy
32
+ - Ansible repo setup if deploy is Capistrano
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'schienenzeppelin'
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__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
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
data/exe/sz ADDED
@@ -0,0 +1,25 @@
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 'schienenzeppelin'
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 %w[-v --version].include? ARGV[0]
17
+ puts Schienenzeppelin::VERSION
18
+ exit 0
19
+ end
20
+
21
+ templates_root = File.expand_path(File.join('..', 'templates'), File.dirname(__FILE__))
22
+ Schienenzeppelin::AppGenerator.source_root templates_root
23
+ Schienenzeppelin::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
24
+
25
+ Schienenzeppelin::AppGenerator.start
data/images/create.png ADDED
Binary file
data/images/error.png ADDED
Binary file
data/images/home.png ADDED
Binary file
data/images/index.png ADDED
Binary file
data/images/login.png ADDED
Binary file
data/images/mobile.png ADDED
Binary file
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/command/base'
4
+ require 'rails/generators/app_base'
5
+ require 'rails/generators'
6
+ require 'rails/generators/app_name'
7
+ require 'rails/generators/rails/app/app_generator'
8
+ require 'bundler'
9
+
10
+ require_relative 'schienenzeppelin/version'
11
+ require_relative 'schienenzeppelin/helper_base'
12
+ Dir[File.join(__dir__, 'schienenzeppelin', 'helpers', '*.rb')].sort.each { |file| require file }
13
+ require_relative 'schienenzeppelin/app_generator'
14
+ require_relative 'schienenzeppelin/app_builder'
15
+
16
+ module Schienenzeppelin
17
+ class Error < StandardError; end
18
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class AppBuilder < Rails::AppBuilder
5
+ def bin
6
+ super
7
+ template 'bin/setup.erb', 'bin/setup', force: true
8
+ end
9
+
10
+ def credentials
11
+ super
12
+ # This sets up credentials using a custom template for both development and production use
13
+ Schienenzeppelin::Helpers::Credentials.apply
14
+ end
15
+
16
+ def readme
17
+ template 'README.md.erb', 'README.md'
18
+ end
19
+
20
+ def ruby_version
21
+ template '.tool-versions.erb', '.tool-versions'
22
+ end
23
+
24
+ def gemfile
25
+ template 'Gemfile.erb', 'Gemfile'
26
+ end
27
+
28
+ def gitignore
29
+ template '.gitignore.erb', '.gitignore'
30
+ end
31
+
32
+ def irbrc
33
+ template '.irbrc.erb', '.irbrc'
34
+ end
35
+
36
+ def docker
37
+ template 'Dockerfile.erb', 'Dockerfile'
38
+ template '.dockerignore.erb', '.dockerignore'
39
+ template 'docker-compose.yml.erb', 'docker-compose.yml'
40
+ end
41
+
42
+ def dotenv
43
+ template '.env.development.erb', '.env.development'
44
+ end
45
+
46
+ def foreman
47
+ template '.foreman.erb', '.foreman'
48
+ template 'Procfile.erb', 'Procfile'
49
+ template 'Procfile.dev.erb', 'Procfile.dev'
50
+ end
51
+
52
+ def database_yml
53
+ if options[:database] == 'postgresql'
54
+ template 'config/postgresql.yml.erb', 'config/database.yml'
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def lograge
61
+ template 'config/initializers/lograge.rb'
62
+ end
63
+
64
+ def sidekiq
65
+ Schienenzeppelin::Helpers::Sidekiq.apply
66
+ end
67
+
68
+ def pundit
69
+ Schienenzeppelin::Helpers::Pundit.apply
70
+ end
71
+
72
+ def rspec
73
+ Schienenzeppelin::Helpers::Rspec.apply
74
+ end
75
+
76
+ def shoulda
77
+ template 'spec/support/shoulda_matchers.rb'
78
+ end
79
+
80
+ def high_voltage
81
+ Schienenzeppelin::Helpers::HighVoltage.apply
82
+ end
83
+
84
+ def factory_bot
85
+ Schienenzeppelin::Helpers::FactoryBot.apply
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class AppGenerator < Rails::Generators::AppGenerator
5
+ class_option :database,
6
+ type: :string,
7
+ aliases: '-d',
8
+ default: 'postgresql',
9
+ desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
10
+
11
+ class_option :skip_active_job,
12
+ type: :boolean, default: true,
13
+ desc: 'Skip Active Job'
14
+
15
+ class_option :skip_jbuilder,
16
+ type: :boolean,
17
+ default: true,
18
+ desc: 'Skip jbuilder gem'
19
+
20
+ class_option :skip_test,
21
+ type: :boolean,
22
+ aliases: '-T', default: true,
23
+ desc: 'Skip test files'
24
+
25
+ class_option :skip_sidekiq,
26
+ type: :boolean, default: false,
27
+ desc: 'Skip sidekiq'
28
+
29
+ class_option :skip_rspec,
30
+ type: :boolean,
31
+ aliases: '-T', default: false,
32
+ desc: 'Skip rspec'
33
+
34
+ def create_config_files
35
+ super
36
+ Schienenzeppelin::Helpers::Generators.apply
37
+ end
38
+
39
+ def create_root_files
40
+ super
41
+
42
+ build(:irbrc)
43
+ build(:foreman)
44
+ build(:dotenv)
45
+ build(:docker)
46
+ build(:docker_compose)
47
+ # TODO: Make optional
48
+ # Schienenzeppelin::Helpers::Rubocop.apply
49
+ end
50
+
51
+ def create_test_files
52
+ build(:test) unless options[:skip_test]
53
+ build(:rspec) unless options[:skip_rspec]
54
+ build(:factory_bot) unless options[:skip_factory_bot]
55
+ build(:shoulda) unless options[:skip_shoulda]
56
+ end
57
+
58
+ def finish_template
59
+ super
60
+ # These require the presence of config/controllers, so they must be done after everything else
61
+ Schienenzeppelin::Helpers::Annotate.apply
62
+ build(:lograge)
63
+ build(:high_voltage)
64
+ build(:pundit)
65
+ Schienenzeppelin::Helpers::Services.apply unless options[:skip_services]
66
+ build(:sidekiq)
67
+ end
68
+
69
+ def after_install
70
+ Schienenzeppelin::Helpers::Devise.apply
71
+ Schienenzeppelin::Helpers::Stimulus.apply
72
+ # TODO: Re-enable with Rails 6.2
73
+ # Schienenzeppelin::Helpers::Hotwire.apply
74
+ Schienenzeppelin::Helpers::Tailwind.apply
75
+ Schienenzeppelin::Helpers::StimulusComponents.apply
76
+
77
+ Schienenzeppelin::Helpers::Home.apply
78
+ Schienenzeppelin::Helpers::Errors.apply
79
+ Schienenzeppelin::Helpers::Scaffold.apply
80
+
81
+ Schienenzeppelin::Helpers::ContinuousIntegration.apply
82
+ Schienenzeppelin::Helpers::Capistrano.apply
83
+ end
84
+
85
+ def self.banner
86
+ "sz new #{arguments.map(&:usage).join(' ')} [options]"
87
+ end
88
+
89
+ protected
90
+
91
+ def get_builder_class
92
+ Schienenzeppelin::AppBuilder
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class HelperBase < Rails::Generators::Base
5
+ include Thor::Actions
6
+ include Rails::Generators::Actions
7
+ include Rails::Generators::AppName
8
+
9
+ def self.apply(options = {})
10
+ new(options).apply
11
+ end
12
+
13
+ def initialize(options, *)
14
+ super
15
+ @options = options
16
+ end
17
+
18
+ private_class_method :new
19
+
20
+ def apply
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def self.default_source_root
25
+ File.expand_path(File.join('..', '..', 'templates'), __dir__)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Annotate < HelperBase
6
+ def apply
7
+ template('lib/tasks/auto_annotate_models.rake', force: true)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Capistrano < HelperBase
6
+ def apply
7
+ say 'Installing and configuring Capistrano'
8
+ run('bundle exec cap install', capture: true)
9
+ directory('lib/capistrano', 'lib/capistrano')
10
+
11
+ configure_deploy
12
+
13
+ template('Capfile.erb', 'Capfile', force: true)
14
+ end
15
+
16
+ private
17
+
18
+ def configure_deploy
19
+ gsub_file('config/deploy.rb', /set :application, .+/, "set :application, '#{app_name}'")
20
+ uncomment_lines('config/deploy.rb', /set :deploy_to/)
21
+ gsub_file('config/deploy.rb', /set :deploy_to, .+"/, 'set :deploy_to, "/home/deploy/#{fetch :application}"') # rubocop:disable Lint/InterpolationCheck
22
+
23
+ uncomment_lines('config/deploy.rb', /set :keep_releases/)
24
+ uncomment_lines('config/deploy.rb', /append :linked_dirs/)
25
+ uncomment_lines('config/deploy.rb', /ask :branch/)
26
+ gsub_file('config/deploy.rb', /ask :branch/, 'set :branch')
27
+ append_to_file('config/deploy.rb') do
28
+ <<~RUBY
29
+ set :passenger_restart_with_sudo, true
30
+ RUBY
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class ContinuousIntegration < HelperBase
6
+ def apply
7
+ say 'Setting up GitHub CI'
8
+ template('.github/workflows/build.yml.erb', '.github/workflows/build.yml')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Credentials < HelperBase
6
+ def apply
7
+ key_path = Pathname.new('config/credentials/production.key')
8
+ create_credential_files(key_path, 'config/credentials/production.yml.enc')
9
+ end
10
+
11
+ private
12
+
13
+ def create_credential_files(key_path, file_path)
14
+ key = ActiveSupport::EncryptedFile.generate_key
15
+ encryption_key_file_generator.add_key_file_silently(key_path, key)
16
+ require 'active_support/encrypted_file'
17
+ ActiveSupport::EncryptedFile.new(
18
+ content_path: file_path,
19
+ key_path: key_path,
20
+ env_key: 'RAILS_MASTER_KEY',
21
+ raise_if_missing_key: true
22
+ ).write(credentials_template)
23
+ end
24
+
25
+ def encryption_key_file_generator
26
+ require 'rails/generators/rails/encrypted_file/encrypted_file_generator'
27
+ Rails::Generators::EncryptionKeyFileGenerator.new
28
+ end
29
+
30
+ def credentials_template
31
+ context = instance_eval('binding', __FILE__, __LINE__)
32
+ source = File.expand_path(find_in_source_paths('config/credentials.yml.erb'))
33
+ match = ERB.version.match(/(\d+\.\d+\.\d+)/)
34
+ capturable_erb = capturable_erb(match, source)
35
+ capturable_erb.tap do |erb|
36
+ erb.filename = source
37
+ end.result(context)
38
+ end
39
+
40
+ def capturable_erb(match, source)
41
+ if match && match[1] >= '2.2.0' # Ruby 2.6+
42
+ CapturableERB.new(::File.binread(source), trim_mode: '-', eoutvar: '@output_buffer')
43
+ else
44
+ CapturableERB.new(::File.binread(source), nil, '-', '@output_buffer')
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end