potassium 5.2.2 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +103 -28
  3. data/.circleci/setup-rubygems.sh +3 -0
  4. data/.gitignore +2 -1
  5. data/.node-version +1 -0
  6. data/.rubocop.yml +530 -0
  7. data/.ruby-version +1 -1
  8. data/CHANGELOG.md +92 -1
  9. data/README.md +51 -45
  10. data/docs/DSL.md +5 -5
  11. data/lib/potassium/assets/.circleci/config.yml.erb +151 -0
  12. data/lib/potassium/assets/.eslintrc.json +352 -0
  13. data/lib/potassium/assets/.github/pull_request_template.md +9 -0
  14. data/lib/potassium/assets/.rubocop.yml +528 -0
  15. data/lib/potassium/assets/.stylelintrc.json +46 -0
  16. data/lib/potassium/assets/Makefile.erb +21 -32
  17. data/lib/potassium/assets/README.yml +59 -15
  18. data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
  19. data/lib/potassium/assets/active_admin/admin_application.js +14 -0
  20. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
  21. data/lib/potassium/assets/app/graphql/graphql_controller.rb +55 -0
  22. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +23 -0
  23. data/lib/potassium/assets/app/graphql/queries/base_query.rb +4 -0
  24. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +4 -0
  25. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +4 -0
  26. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +5 -0
  27. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +5 -0
  28. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +7 -0
  29. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +5 -0
  30. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +4 -0
  31. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +4 -0
  32. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +10 -0
  33. data/lib/potassium/assets/app/graphql/types/query_type.rb +13 -0
  34. data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
  35. data/lib/potassium/assets/app/uploaders/base_uploader.rb +11 -0
  36. data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
  37. data/lib/potassium/assets/app/views/shared/_gtm_body.html.erb +4 -0
  38. data/lib/potassium/assets/app/views/shared/_gtm_head.html.erb +7 -0
  39. data/lib/potassium/assets/bin/release +1 -1
  40. data/lib/potassium/assets/bin/setup.erb +1 -1
  41. data/lib/potassium/assets/config/database_mysql.yml.erb +2 -2
  42. data/lib/potassium/assets/config/database_postgresql.yml.erb +2 -2
  43. data/lib/potassium/assets/config/graphql_playground.rb +20 -0
  44. data/lib/potassium/assets/config/puma.rb +1 -1
  45. data/lib/potassium/assets/config/shrine.rb +36 -0
  46. data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +2 -1
  47. data/lib/potassium/assets/package.json +4 -1
  48. data/lib/potassium/assets/redis.yml +1 -2
  49. data/lib/potassium/assets/testing/rails_helper.rb +2 -0
  50. data/lib/potassium/cli/commands/create.rb +12 -19
  51. data/lib/potassium/cli_options.rb +77 -26
  52. data/lib/potassium/helpers/gem-helpers.rb +1 -1
  53. data/lib/potassium/helpers/template-helpers.rb +8 -0
  54. data/lib/potassium/newest_version_ensurer.rb +19 -36
  55. data/lib/potassium/node_version_ensurer.rb +30 -0
  56. data/lib/potassium/recipes/admin.rb +3 -3
  57. data/lib/potassium/recipes/annotate.rb +1 -1
  58. data/lib/potassium/recipes/api.rb +93 -21
  59. data/lib/potassium/recipes/background_processor.rb +66 -19
  60. data/lib/potassium/recipes/ci.rb +10 -38
  61. data/lib/potassium/recipes/data_migrate.rb +44 -0
  62. data/lib/potassium/recipes/database.rb +4 -0
  63. data/lib/potassium/recipes/database_container.rb +7 -5
  64. data/lib/potassium/recipes/draper.rb +1 -10
  65. data/lib/potassium/recipes/file_storage.rb +66 -0
  66. data/lib/potassium/recipes/front_end.rb +225 -9
  67. data/lib/potassium/recipes/github.rb +93 -15
  68. data/lib/potassium/recipes/google_tag_manager.rb +90 -0
  69. data/lib/potassium/recipes/heroku.rb +42 -29
  70. data/lib/potassium/recipes/mailer.rb +18 -2
  71. data/lib/potassium/recipes/monitoring.rb +5 -0
  72. data/lib/potassium/recipes/node.rb +21 -0
  73. data/lib/potassium/recipes/rack_cors.rb +18 -15
  74. data/lib/potassium/recipes/schedule.rb +17 -2
  75. data/lib/potassium/recipes/style.rb +21 -3
  76. data/lib/potassium/recipes/vue_admin.rb +124 -0
  77. data/lib/potassium/templates/application.rb +10 -7
  78. data/lib/potassium/version.rb +7 -4
  79. data/potassium.gemspec +11 -6
  80. data/spec/features/api_spec.rb +25 -0
  81. data/spec/features/background_processor_spec.rb +19 -6
  82. data/spec/features/ci_spec.rb +7 -4
  83. data/spec/features/data_migrate_spec.rb +14 -0
  84. data/spec/features/database_container_spec.rb +1 -5
  85. data/spec/features/draper_spec.rb +1 -6
  86. data/spec/features/file_storage_spec.rb +75 -0
  87. data/spec/features/front_end_spec.rb +102 -0
  88. data/spec/features/github_spec.rb +53 -8
  89. data/spec/features/google_tag_manager_spec.rb +59 -0
  90. data/spec/features/graphql_spec.rb +71 -0
  91. data/spec/features/heroku_spec.rb +1 -1
  92. data/spec/features/mailer_spec.rb +16 -0
  93. data/spec/features/new_project_spec.rb +6 -14
  94. data/spec/features/node_spec.rb +28 -0
  95. data/spec/features/power_types_spec.rb +5 -16
  96. data/spec/features/schedule_spec.rb +11 -4
  97. data/spec/features/vue_admin_spec.rb +47 -0
  98. data/spec/spec_helper.rb +5 -0
  99. data/spec/support/fake_octokit.rb +31 -0
  100. data/spec/support/potassium_test_helpers.rb +26 -9
  101. data/tmp/.keep +0 -0
  102. metadata +152 -46
  103. data/lib/potassium/assets/.circleci/config.yml +0 -20
  104. data/lib/potassium/assets/Dockerfile.ci +0 -6
  105. data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
  106. data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
  107. data/lib/potassium/assets/api/api_error_concern.rb +0 -32
  108. data/lib/potassium/assets/api/base_controller.rb +0 -9
  109. data/lib/potassium/assets/api/draper_responder.rb +0 -62
  110. data/lib/potassium/assets/api/responder.rb +0 -41
  111. data/lib/potassium/assets/aws.rb +0 -1
  112. data/lib/potassium/assets/bin/cibuild.erb +0 -100
  113. data/lib/potassium/assets/docker-compose.ci.yml +0 -11
  114. data/lib/potassium/assets/sidekiq_scheduler.yml +0 -9
  115. data/lib/potassium/assets/testing/paperclip.rb +0 -59
  116. data/lib/potassium/recipes/active_storage.rb +0 -40
  117. data/lib/potassium/recipes/angular_admin.rb +0 -56
  118. data/lib/potassium/recipes/aws_sdk.rb +0 -7
  119. data/lib/potassium/recipes/paperclip.rb +0 -47
  120. data/spec/features/active_storage_spec.rb +0 -30
  121. data/spec/features/front_end.rb +0 -30
@@ -1,20 +0,0 @@
1
- version: 2
2
- jobs:
3
- build:
4
- working_directory: ~/app
5
-
6
- docker:
7
- - image: platanus/compose:1.22.0
8
-
9
- steps:
10
- - checkout
11
- - setup_remote_docker
12
-
13
- - run: docker info
14
- - run: docker-compose -f docker-compose.ci.yml pull
15
- - run: docker-compose -f docker-compose.ci.yml build test
16
- - run: bin/cibuild services
17
- - run: bin/cibuild deps
18
-
19
- - run: bin/cibuild db
20
- - run: bin/cibuild tests
@@ -1,6 +0,0 @@
1
- FROM platanus/ruby:2.5
2
-
3
- RUN mkdir /app
4
- WORKDIR /app
5
-
6
- ADD . /app
@@ -1,4 +0,0 @@
1
- #= require active_admin/base
2
- #= require angular
3
- #= require admin_app
4
- #= require_tree ./admin
@@ -1,8 +0,0 @@
1
- class ActiveAdmin::Views::Pages::Base
2
- alias_method :old_add_classes_to_body, :add_classes_to_body
3
-
4
- def add_classes_to_body
5
- old_add_classes_to_body
6
- @body.set_attribute "ng-app", "ActiveAdmin"
7
- end
8
- end
@@ -1,32 +0,0 @@
1
- module ApiErrorConcern
2
- extend ActiveSupport::Concern
3
-
4
- included do
5
- rescue_from "Exception" do |exception|
6
- logger.error exception.message
7
- logger.error exception.backtrace.join("\n")
8
- respond_api_error(:internal_server_error, message: "server_error",
9
- type: exception.class.to_s,
10
- detail: exception.message)
11
- end
12
-
13
- rescue_from "ActiveRecord::RecordNotFound" do |exception|
14
- respond_api_error(:not_found, message: "record_not_found",
15
- detail: exception.message)
16
- end
17
-
18
- rescue_from "ActiveModel::ForbiddenAttributesError" do |exception|
19
- respond_api_error(:bad_request, message: "protected_attributes",
20
- detail: exception.message)
21
- end
22
-
23
- rescue_from "ActiveRecord::RecordInvalid" do |exception|
24
- respond_api_error(:bad_request, message: "invalid_attributes",
25
- errors: exception.record.errors)
26
- end
27
- end
28
-
29
- def respond_api_error(status, error = {})
30
- render json: error, status: status
31
- end
32
- end
@@ -1,9 +0,0 @@
1
- class Api::V1::BaseController < ApplicationController
2
- if Rails.env.production?
3
- include ApiErrorConcern
4
- end
5
-
6
- self.responder = ApiResponder
7
-
8
- respond_to :json
9
- end
@@ -1,62 +0,0 @@
1
- class ApiResponder < ActionController::Responder
2
- def respond
3
- return display_errors if has_errors?
4
- return head :no_content if delete?
5
-
6
- display resource, status_code: status_code
7
- end
8
-
9
- private
10
-
11
- def display(_resource, given_options = {})
12
- controller.render options.merge(given_options).merge(
13
- json: serializer.as_json
14
- )
15
- end
16
-
17
- def serializer
18
- serializer_class = ActiveModel::Serializer.serializer_for(resource)
19
- if serializer_class.present?
20
- serializer_options = infer_serializer(serializer_class).merge(options)
21
- serializer_class.new(decorated_resource, serializer_options)
22
- else
23
- decorated_resource
24
- end
25
- end
26
-
27
- def status_code
28
- return :created if post?
29
- :ok
30
- end
31
-
32
- def display_errors
33
- controller.render(
34
- status: :unprocessable_entity,
35
- json: { msg: "invalid_attributes", errors: format_errors }
36
- )
37
- end
38
-
39
- def format_errors
40
- resource.errors.as_json
41
- end
42
-
43
- def infer_serializer(serializer_class)
44
- if serializer_class == ActiveModel::ArraySerializer
45
- s = options.delete(:each_serializer) || "#{resource.klass}Serializer".constantize
46
- { each_serializer: s }
47
- else
48
- s = options.delete(:serializer) || "#{resource.class}Serializer".constantize
49
- { serializer: s }
50
- end
51
- end
52
-
53
- def decorated_resource
54
- if resource.respond_to?(:decorate)
55
- resource.decorate
56
- else
57
- resource
58
- end
59
- rescue Draper::UninferrableDecoratorError
60
- resource
61
- end
62
- end
@@ -1,41 +0,0 @@
1
- class ApiResponder < ActionController::Responder
2
- def respond
3
- return display_errors if has_errors?
4
- return head :no_content if delete?
5
-
6
- display resource, status_code: status_code
7
- end
8
-
9
- private
10
-
11
- def display(_resource, given_options = {})
12
- controller.render options.merge(given_options).merge(
13
- json: serializer.as_json
14
- )
15
- end
16
-
17
- def serializer
18
- serializer_class = ActiveModel::Serializer.serializer_for(resource)
19
- if serializer_class.present?
20
- serializer_class.new(resource, options)
21
- else
22
- resource
23
- end
24
- end
25
-
26
- def status_code
27
- return :created if post?
28
- :ok
29
- end
30
-
31
- def display_errors
32
- controller.render(
33
- status: :unprocessable_entity,
34
- json: { msg: "invalid_attributes", errors: format_errors }
35
- )
36
- end
37
-
38
- def format_errors
39
- resource.errors.as_json
40
- end
41
- end
@@ -1 +0,0 @@
1
- Aws::VERSION = Gem.loaded_specs["aws-sdk"].version
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env bash
2
- trap "exit" SIGINT SIGTERM
3
-
4
- command -v docker >/dev/null 2>&1 && docker info >/dev/null || {
5
- printf >&2 "\e[31mI require docker but it's not installed. Aborting.\e[0m\n"; exit 1;
6
- }
7
-
8
- DOCKER_COMPOSE_ARGS="-f docker-compose.ci.yml"
9
-
10
- # Build Image
11
- build(){
12
- docker-compose $DOCKER_COMPOSE_ARGS build test
13
- }
14
-
15
- # Wait services to be ready
16
- wait_services(){
17
- function test_service {
18
- docker-compose $DOCKER_COMPOSE_ARGS run test sh -c "nc -z $1 $2"
19
- }
20
-
21
- count=0
22
- # Chain tests together by using &&
23
- until (
24
- <% if(selected?(:database, :mysql) || selected?(:database, :postgresql))-%>
25
- test_service '$DB_HOST' '$DB_PORT' && \
26
- <% end-%>
27
- echo "Services ready"
28
- )
29
- do
30
- ((count++))
31
- if [ $count -gt 50 ]
32
- then
33
- echo "Services didn't become ready in time"
34
- exit 1
35
- else
36
- echo "Waiting for services to become ready..."
37
- fi
38
- sleep 0.5
39
- done
40
- }
41
-
42
- # Prepare dependencies
43
- dependencies(){
44
- docker-compose $DOCKER_COMPOSE_ARGS run test bundle install
45
- }
46
-
47
- assets() {
48
- docker-compose $DOCKER_COMPOSE_ARGS run test /bin/bash -c "bin/setup && bundle exec rake assets:precompile"
49
- }
50
-
51
- # Prepare database
52
- database(){
53
- docker-compose $DOCKER_COMPOSE_ARGS run test bundle exec rake db:create db:schema:load
54
- }
55
-
56
- # Run the specs
57
- tests(){
58
- [ -n "$CI" ] && {
59
- RSPEC_JUNIT_ARGS="-r rspec_junit_formatter --format RspecJunitFormatter -o $HOME/.rspec_reports/junit.xml"
60
- RSPEC_FORMAT_ARGS="--format progress --no-color"
61
- }
62
- docker-compose $DOCKER_COMPOSE_ARGS run test bundle exec rspec spec $RSPEC_FORMAT_ARGS $RSPEC_JUNIT_ARGS
63
- }
64
-
65
- # Run the complete ci build
66
- no_ci(){
67
- build
68
- wait_services
69
- dependencies
70
- assets
71
- database
72
- tests
73
- }
74
-
75
- case "$1" in
76
- "")
77
- no_ci
78
- ;;
79
- "services")
80
- wait_services
81
- ;;
82
- "deps"|"dependencies")
83
- dependencies
84
- ;;
85
- "assets")
86
- assets
87
- ;;
88
- "db"|"database")
89
- database
90
- ;;
91
- "specs"|"tests")
92
- tests
93
- ;;
94
- "build")
95
- build
96
- ;;
97
- *)
98
- echo "Usage: cibuild [services|deps|assets|db|specs|build]"
99
- ;;
100
- esac
@@ -1,11 +0,0 @@
1
- version: '3.4'
2
-
3
- services:
4
- test:
5
- build:
6
- context: "."
7
- dockerfile: Dockerfile.ci
8
- volumes:
9
- - "./vendor/bundle:/usr/local/bundle"
10
- environment:
11
- RACK_ENV: test
@@ -1,9 +0,0 @@
1
- production:
2
- :concurrency: 5
3
- :queues:
4
- - default
5
- :schedule:
6
- # an_scheduled_task:
7
- # cron: '0 * * * * *' # Runs once per minute
8
- # class: ExampleJob
9
- # args: ['a', 'b']
@@ -1,59 +0,0 @@
1
- require "paperclip/matchers"
2
-
3
- include ActionDispatch::TestProcess
4
-
5
- test_files_path = ":rails_root/test_files/:class/:attachment/:id_partition/:filename"
6
- Paperclip::Attachment.default_options[:path] = test_files_path
7
-
8
- RSpec.configure do |config|
9
- config.fixture_path = "#{::Rails.root}/spec/assets"
10
-
11
- config.include Paperclip::Shoulda::Matchers
12
-
13
- config.after(:suite) do
14
- FileUtils.rm_rf("#{Rails.root}/test_files")
15
- FileUtils.rm_rf("#{Rails.root}/public/uploads")
16
- end
17
- end
18
-
19
- def fixture_asset(file_name, mime)
20
- file_path = Rails.root.to_s + "/spec/assets/" + file_name
21
- fixture_file_upload(file_path, mime)
22
- rescue
23
- fixture_file_upload(file_name, mime)
24
- end
25
-
26
- # GENERAL CONFIG
27
- # On test environment, paperclip attachments will be generated under /test_files directory.
28
- # After running all the specs, the test_files folder will be deleted.
29
- #
30
- # SHOULDA MATCHERS
31
- # Including Paperclip::Shoulda::Matchers will allow you to use special matchers
32
- # to work with paperclip. For example:
33
- #
34
- # describe User do
35
- # it { should have_attached_file(:avatar) }
36
- # it { should validate_attachment_presence(:avatar) }
37
- # it { should validate_attachment_content_type(:avatar).
38
- # allowing('image/png', 'image/gif').
39
- # rejecting('text/plain', 'text/xml') }
40
- # it { should validate_attachment_size(:avatar).
41
- # less_than(2.megabytes) }
42
- # end
43
- #
44
- # ASSETS
45
- # Your attachments go into /spec/assets directory. You can access them...
46
- #
47
- # From your factories:
48
- #
49
- # FactoryBot.define do
50
- # factory :ticket do
51
- # attachment { fixture_asset("platanus.png", "image/png") }
52
- # end
53
- # end
54
- #
55
- # From your specs:
56
- #
57
- # it "gets file name" do
58
- # expect(fixture_asset("platanus.png", "image/png").original_filename).to eq("platanus.png")
59
- # end
@@ -1,40 +0,0 @@
1
- class Recipes::ActiveStorage < Rails::AppBuilder
2
- def ask
3
- active_storage = answer(:active_storage) do
4
- Ask.confirm("Do you want to use ActiveStorage for uploads?")
5
- end
6
-
7
- set(:active_storage, active_storage)
8
- end
9
-
10
- def create
11
- return unless selected?(:active_storage)
12
- add_active_storage
13
- end
14
-
15
- def install
16
- add_active_storage
17
- end
18
-
19
- def installed?
20
- file_exist?('config/storage.yml')
21
- end
22
-
23
- private
24
-
25
- def add_active_storage
26
- after(:gem_install) { run("bundle exec rails active_storage:install") }
27
-
28
- add_readme_section :internal_dependencies, :storage
29
-
30
- copy_file("../assets/config/storage.yml", "config/storage.yml", force: true)
31
-
32
- append_to_file '.env.development', "AWS_REGION=\n"
33
- append_to_file '.env.development', "S3_BUCKET=\n"
34
-
35
- raise_delivery_errors_regexp = /config.active_storage.service = :local\n/
36
- gsub_file 'config/environments/production.rb', raise_delivery_errors_regexp do
37
- "config.active_storage.service = :amazon"
38
- end
39
- end
40
- end
@@ -1,56 +0,0 @@
1
- class Recipes::AngularAdmin < Rails::AppBuilder
2
- def ask
3
- if selected?(:admin_mode)
4
- angular_admin = answer(:"angular-admin") do
5
- Ask.confirm "Do you want Angular support for ActiveAdmin?"
6
- end
7
- set(:angular_admin, angular_admin)
8
- end
9
- end
10
-
11
- def create
12
- recipe = self
13
- if selected?(:angular_admin)
14
- after(:admin_install) do
15
- recipe.add_angular_admin
16
- end
17
- end
18
- end
19
-
20
- def install
21
- active_admin = load_recipe(:admin)
22
- if active_admin.installed?
23
- add_angular_admin
24
- else
25
- info "ActiveAdmin can't be installed because Active Admin isn't installed."
26
- end
27
- end
28
-
29
- def installed?
30
- dir_exist?("app/assets/javascripts/admin")
31
- end
32
-
33
- def add_angular_admin
34
- copy_file '../assets/active_admin/init_activeadmin_angular.rb',
35
- 'config/initializers/init_activeadmin_angular.rb'
36
-
37
- create_file 'app/assets/javascripts/admin_app.js', "angular.module('ActiveAdmin', []);"
38
-
39
- copy_file '../assets/active_admin/active_admin.js.coffee',
40
- 'app/assets/javascripts/active_admin.js.coffee',
41
- force: true
42
-
43
- empty_directory 'app/assets/javascripts/admin'
44
- empty_directory 'app/assets/javascripts/admin/controllers'
45
- empty_directory 'app/assets/javascripts/admin/services'
46
- empty_directory 'app/assets/javascripts/admin/directives'
47
-
48
- create_file 'app/assets/javascripts/admin/controllers/.keep'
49
- create_file 'app/assets/javascripts/admin/services/.keep'
50
- create_file 'app/assets/javascripts/admin/directives/.keep'
51
-
52
- inside('.') do
53
- run('bin/yarn add angular --save')
54
- end
55
- end
56
- end