From 06c8d27eb1fd31da066dc5cd7d0d37346a35e72a Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Sat, 14 Oct 2023 14:13:17 -0400 Subject: [PATCH] Suspenders 3.0.0 In an effort to improve the developer experience and reduce technical debt, we replace the existing project with the output from running: ``` rails plugin new suspenders ``` This will allow us to use existing [testing helpers][] provided by Rails. Because of this, we deliberately switch from RSpec to MiniTest. Additionally, we move away from [calver][]. Prior to that the latest major version was `1`. This feels like a good opportunity to go back to `semver` and start fresh with `3.0.0` [testing helpers]: https://edgeguides.rubyonrails.org/generators.html#testing-generators [calver]: https://calver.org --- .github/workflows/main.yml | 59 +-- .gitignore | 15 +- CONTRIBUTING.md | 74 ++- Gemfile | 9 + Gemfile.lock | 241 +++++++++ MIT-LICENSE | 20 + README.md | 230 ++------ Rakefile | 12 +- USAGE | 13 - bin/rake | 16 - bin/rspec | 16 - bin/setup | 15 +- bin/suspenders | 63 --- bin/test | 5 + docs/heroku_deploy.md | 19 - docs/rails_7.md | 5 - lib/suspenders.rb | 38 +- lib/suspenders/actions.rb | 106 ---- .../actions/strip_comments_action.rb | 254 --------- lib/suspenders/adapters/heroku.rb | 136 ----- lib/suspenders/app_builder.rb | 267 ---------- lib/suspenders/exit_on_failure.rb | 19 - .../generators/accessibility_generator.rb | 12 - .../generators/advisories_generator.rb | 15 - .../generators/analytics_generator.rb | 24 - lib/suspenders/generators/app_generator.rb | 215 -------- lib/suspenders/generators/base.rb | 60 --- lib/suspenders/generators/ci_generator.rb | 32 -- .../generators/db_optimizations_generator.rb | 18 - .../generators/factories_generator.rb | 22 - lib/suspenders/generators/forms_generator.rb | 18 - .../generators/inline_svg_generator.rb | 14 - lib/suspenders/generators/jobs_generator.rb | 37 -- .../generators/js_driver_generator.rb | 14 - lib/suspenders/generators/json_generator.rb | 14 - lib/suspenders/generators/lint_generator.rb | 14 - .../production/compression_generator.rb | 14 - .../production/deployment_generator.rb | 16 - .../generators/production/email_generator.rb | 34 -- .../production/force_tls_generator.rb | 11 - .../production/manifest_generator.rb | 25 - .../generators/production/single_redirect.rb | 15 - .../production/timeout_generator.rb | 22 - .../generators/profiler_generator.rb | 35 -- lib/suspenders/generators/runner_generator.rb | 48 -- .../staging/pull_requests_generator.rb | 25 - lib/suspenders/generators/static_generator.rb | 14 - .../generators/stylelint_generator.rb | 71 --- .../generators/stylesheet_base_generator.rb | 15 - .../generators/testing_generator.rb | 43 -- lib/suspenders/generators/views_generator.rb | 25 - lib/suspenders/railtie.rb | 4 + lib/suspenders/version.rb | 10 +- lib/tasks/suspenders_tasks.rake | 4 + spec/adapters/heroku_spec.rb | 98 ---- spec/expand_json_spec.rb | 89 ---- spec/features/api_spec.rb | 18 - spec/features/cli_help_spec.rb | 36 -- spec/features/github_spec.rb | 16 - spec/features/heroku_spec.rb | 63 --- spec/features/new_project_spec.rb | 344 ------------ spec/spec_helper.rb | 17 - spec/support/be_executable_matcher.rb | 7 - spec/support/contain_json_matcher.rb | 30 -- spec/support/env_path.rb | 19 - spec/support/exist_as_a_file_matcher.rb | 7 - spec/support/fake_bundler.rb | 55 -- spec/support/fake_bundler_matchers.rb | 58 --- spec/support/fake_github.rb | 17 - spec/support/fake_heroku.rb | 49 -- spec/support/fake_yarn.rb | 24 - spec/support/fake_yarn_matchers.rb | 25 - spec/support/fakes/bin/heroku | 6 - spec/support/fakes/bin/hub | 6 - spec/support/fakes/bundler/audit/task.rb | 11 - spec/support/fakes/bundler_bin/bundle | 6 - spec/support/fakes/fake_rails.rb | 21 - spec/support/feature_test_helpers.rb | 181 ------- spec/support/file_operations.rb | 34 -- spec/support/fixtures/dummy_app/Gemfile | 7 - spec/support/fixtures/dummy_app/Rakefile | 8 - spec/support/fixtures/dummy_app/bin/yarn | 6 - .../config/environments/development.rb | 28 - .../config/environments/production.rb | 24 - spec/support/generator_matchers.rb | 45 -- spec/support/generator_test_helpers.rb | 71 --- spec/support/match_contents_matcher.rb | 20 - spec/support/message_matcher.rb | 21 - spec/support/output_stub.rb | 15 - spec/support/rails_stub.rb | 17 - spec/support/rails_template.rb | 1 - spec/support/test_paths.rb | 40 -- .../actions/strip_comments_action_spec.rb | 489 ------------------ spec/suspenders/app_generator_spec.rb | 7 - spec/suspenders/exit_on_failure_spec.rb | 41 -- .../accessibility_generator_spec.rb | 38 -- .../generators/advisories_generator_spec.rb | 80 --- spec/suspenders/generators/base_spec.rb | 7 - .../generators/ci_generator_spec.rb | 99 ---- .../db_optimizations_generator_spec.rb | 49 -- .../generators/inline_svg_generator_spec.rb | 47 -- .../generators/json_generator_spec.rb | 45 -- .../generators/lint_generator_spec.rb | 50 -- .../production/compression_generator_spec.rb | 25 - .../production/deployment_generator_spec.rb | 51 -- .../production/email_generator_spec.rb | 79 --- .../production/manifest_generator_spec.rb | 53 -- .../production/single_redirect_spec.rb | 33 -- .../generators/profiler_generator_spec.rb | 102 ---- .../generators/runner_generator_spec.rb | 92 ---- .../staging/pull_requests_generator_spec.rb | 61 --- .../generators/static_generator_spec.rb | 45 -- .../generators/stylelint_generator_spec.rb | 89 ---- suspenders.gemspec | 54 +- templates/Gemfile.erb | 48 -- templates/Procfile | 2 - templates/README.md.erb | 28 - templates/_analytics.html.erb | 8 - templates/_css_overrides.html.erb | 7 - templates/_flashes.html.erb | 7 - templates/action_mailer.rb | 5 - templates/active_job.rb | 14 - templates/application.postcss.css | 1 - templates/bin_auto_migrate | 5 - templates/bin_deploy | 10 - templates/bin_setup | 28 - templates/bin_setup_review_app.erb | 21 - templates/bin_yarn | 18 - templates/bundler_audit.rake | 4 - templates/chromedriver.rb | 27 - templates/circle.yml.erb | 6 - templates/config_locales_en.yml.erb | 19 - templates/descriptions/advisories.md | 5 - templates/descriptions/analytics.md | 4 - templates/descriptions/ci.md | 4 - templates/descriptions/compression.md | 4 - templates/descriptions/db_optimizations.md | 2 - templates/descriptions/deployment.md | 5 - templates/descriptions/email.md | 9 - templates/descriptions/factories.md | 12 - templates/descriptions/force_tls.md | 1 - templates/descriptions/forms.md | 1 - templates/descriptions/inline_svg.md | 2 - templates/descriptions/jobs.md | 3 - templates/descriptions/js_driver.md | 4 - templates/descriptions/json.md | 1 - templates/descriptions/lint.md | 3 - templates/descriptions/manifest.md | 2 - templates/descriptions/profiler.md | 7 - templates/descriptions/pull_requests.md | 4 - templates/descriptions/runner.md | 10 - templates/descriptions/single_redirect.md | 1 - templates/descriptions/static.md | 5 - templates/descriptions/stylelint.md | 3 - templates/descriptions/stylesheet_base.md | 1 - templates/descriptions/testing.md | 9 - templates/descriptions/timeout.md | 4 - templates/descriptions/views.md | 8 - templates/dev.rake | 12 - templates/email.rb | 3 - templates/errors.rb | 35 -- templates/factories.rb | 2 - templates/factory_bot_rspec.rb | 5 - templates/flashes_helper.rb | 5 - templates/hound.yml | 15 - templates/i18n.rb | 3 - templates/inline_svg.rb | 3 - templates/json_encoding.rb | 1 - templates/oj.rb | 3 - templates/partials/ci_simplecov.rb | 14 - .../db_optimizations_configuration.rb | 7 - templates/partials/deployment_readme.md | 8 - templates/partials/email_smtp.rb | 2 - templates/partials/profiler_readme.md | 8 - templates/partials/pull_requests_config.rb | 5 - templates/partials/runner_readme.md | 31 -- templates/partials/runner_setup.rb | 2 - templates/postcss.config.js | 8 - templates/postgresql_database.yml.erb | 20 - templates/rack_mini_profiler.rb | 7 - templates/rails_helper.rb | 25 - templates/sample_env | 12 - templates/secrets.yml | 8 - templates/shoulda_matchers_config_rspec.rb | 6 - templates/smtp.rb | 9 - templates/spec_helper.rb | 25 - templates/stylelintrc.json | 3 - templates/suspenders_gitignore | 18 - templates/suspenders_layout.html.erb.erb | 23 - test/dummy/Rakefile | 6 + .../dummy/app/assets/images/.keep | 0 .../app/assets/stylesheets/application.css | 1 + .../app/channels/application_cable/channel.rb | 4 + .../channels/application_cable/connection.rb | 4 + .../app/controllers/application_controller.rb | 2 + test/dummy/app/controllers/concerns/.keep | 0 test/dummy/app/helpers/application_helper.rb | 2 + test/dummy/app/jobs/application_job.rb | 7 + test/dummy/app/mailers/application_mailer.rb | 4 + test/dummy/app/models/application_record.rb | 3 + test/dummy/app/models/concerns/.keep | 0 .../app/views/layouts/application.html.erb | 15 + test/dummy/app/views/layouts/mailer.html.erb | 13 + test/dummy/app/views/layouts/mailer.text.erb | 1 + test/dummy/bin/rails | 4 + test/dummy/bin/rake | 4 + test/dummy/bin/setup | 33 ++ test/dummy/config.ru | 6 + test/dummy/config/application.rb | 26 + test/dummy/config/boot.rb | 5 + test/dummy/config/cable.yml | 10 + test/dummy/config/database.yml | 25 + test/dummy/config/environment.rb | 5 + test/dummy/config/environments/development.rb | 73 +++ test/dummy/config/environments/production.rb | 91 ++++ test/dummy/config/environments/test.rb | 64 +++ .../initializers/content_security_policy.rb | 25 + .../initializers/filter_parameter_logging.rb | 8 + test/dummy/config/initializers/inflections.rb | 16 + .../config/initializers/permissions_policy.rb | 13 + test/dummy/config/locales/en.yml | 31 ++ test/dummy/config/puma.rb | 35 ++ test/dummy/config/routes.rb | 10 + test/dummy/config/storage.yml | 34 ++ test/dummy/lib/assets/.keep | 0 test/dummy/log/.keep | 0 test/dummy/public/404.html | 67 +++ test/dummy/public/422.html | 67 +++ test/dummy/public/500.html | 66 +++ .../public/apple-touch-icon-precomposed.png | 0 test/dummy/public/apple-touch-icon.png | 0 test/dummy/public/favicon.ico | 0 test/dummy/storage/.keep | 0 test/dummy/tmp/.keep | 0 test/dummy/tmp/pids/.keep | 0 test/dummy/tmp/storage/.keep | 0 test/suspenders_test.rb | 15 + test/test_helper.rb | 14 + 238 files changed, 1228 insertions(+), 6029 deletions(-) create mode 100644 Gemfile.lock create mode 100644 MIT-LICENSE delete mode 100644 USAGE delete mode 100755 bin/rake delete mode 100755 bin/rspec delete mode 100755 bin/suspenders create mode 100755 bin/test delete mode 100644 docs/heroku_deploy.md delete mode 100644 docs/rails_7.md delete mode 100644 lib/suspenders/actions.rb delete mode 100644 lib/suspenders/actions/strip_comments_action.rb delete mode 100644 lib/suspenders/adapters/heroku.rb delete mode 100644 lib/suspenders/app_builder.rb delete mode 100644 lib/suspenders/exit_on_failure.rb delete mode 100644 lib/suspenders/generators/accessibility_generator.rb delete mode 100644 lib/suspenders/generators/advisories_generator.rb delete mode 100644 lib/suspenders/generators/analytics_generator.rb delete mode 100644 lib/suspenders/generators/app_generator.rb delete mode 100644 lib/suspenders/generators/base.rb delete mode 100644 lib/suspenders/generators/ci_generator.rb delete mode 100644 lib/suspenders/generators/db_optimizations_generator.rb delete mode 100644 lib/suspenders/generators/factories_generator.rb delete mode 100644 lib/suspenders/generators/forms_generator.rb delete mode 100644 lib/suspenders/generators/inline_svg_generator.rb delete mode 100644 lib/suspenders/generators/jobs_generator.rb delete mode 100644 lib/suspenders/generators/js_driver_generator.rb delete mode 100644 lib/suspenders/generators/json_generator.rb delete mode 100644 lib/suspenders/generators/lint_generator.rb delete mode 100644 lib/suspenders/generators/production/compression_generator.rb delete mode 100644 lib/suspenders/generators/production/deployment_generator.rb delete mode 100644 lib/suspenders/generators/production/email_generator.rb delete mode 100644 lib/suspenders/generators/production/force_tls_generator.rb delete mode 100644 lib/suspenders/generators/production/manifest_generator.rb delete mode 100644 lib/suspenders/generators/production/single_redirect.rb delete mode 100644 lib/suspenders/generators/production/timeout_generator.rb delete mode 100644 lib/suspenders/generators/profiler_generator.rb delete mode 100644 lib/suspenders/generators/runner_generator.rb delete mode 100644 lib/suspenders/generators/staging/pull_requests_generator.rb delete mode 100644 lib/suspenders/generators/static_generator.rb delete mode 100644 lib/suspenders/generators/stylelint_generator.rb delete mode 100644 lib/suspenders/generators/stylesheet_base_generator.rb delete mode 100644 lib/suspenders/generators/testing_generator.rb delete mode 100644 lib/suspenders/generators/views_generator.rb create mode 100644 lib/suspenders/railtie.rb create mode 100644 lib/tasks/suspenders_tasks.rake delete mode 100644 spec/adapters/heroku_spec.rb delete mode 100644 spec/expand_json_spec.rb delete mode 100644 spec/features/api_spec.rb delete mode 100644 spec/features/cli_help_spec.rb delete mode 100644 spec/features/github_spec.rb delete mode 100644 spec/features/heroku_spec.rb delete mode 100644 spec/features/new_project_spec.rb delete mode 100644 spec/spec_helper.rb delete mode 100644 spec/support/be_executable_matcher.rb delete mode 100644 spec/support/contain_json_matcher.rb delete mode 100644 spec/support/env_path.rb delete mode 100644 spec/support/exist_as_a_file_matcher.rb delete mode 100644 spec/support/fake_bundler.rb delete mode 100644 spec/support/fake_bundler_matchers.rb delete mode 100644 spec/support/fake_github.rb delete mode 100644 spec/support/fake_heroku.rb delete mode 100644 spec/support/fake_yarn.rb delete mode 100644 spec/support/fake_yarn_matchers.rb delete mode 100755 spec/support/fakes/bin/heroku delete mode 100755 spec/support/fakes/bin/hub delete mode 100644 spec/support/fakes/bundler/audit/task.rb delete mode 100755 spec/support/fakes/bundler_bin/bundle delete mode 100644 spec/support/fakes/fake_rails.rb delete mode 100644 spec/support/feature_test_helpers.rb delete mode 100644 spec/support/file_operations.rb delete mode 100644 spec/support/fixtures/dummy_app/Gemfile delete mode 100644 spec/support/fixtures/dummy_app/Rakefile delete mode 100755 spec/support/fixtures/dummy_app/bin/yarn delete mode 100644 spec/support/fixtures/dummy_app/config/environments/development.rb delete mode 100644 spec/support/fixtures/dummy_app/config/environments/production.rb delete mode 100644 spec/support/generator_matchers.rb delete mode 100644 spec/support/generator_test_helpers.rb delete mode 100644 spec/support/match_contents_matcher.rb delete mode 100644 spec/support/message_matcher.rb delete mode 100644 spec/support/output_stub.rb delete mode 100644 spec/support/rails_stub.rb delete mode 100644 spec/support/rails_template.rb delete mode 100644 spec/support/test_paths.rb delete mode 100644 spec/suspenders/actions/strip_comments_action_spec.rb delete mode 100644 spec/suspenders/app_generator_spec.rb delete mode 100644 spec/suspenders/exit_on_failure_spec.rb delete mode 100644 spec/suspenders/generators/accessibility_generator_spec.rb delete mode 100644 spec/suspenders/generators/advisories_generator_spec.rb delete mode 100644 spec/suspenders/generators/base_spec.rb delete mode 100644 spec/suspenders/generators/ci_generator_spec.rb delete mode 100644 spec/suspenders/generators/db_optimizations_generator_spec.rb delete mode 100644 spec/suspenders/generators/inline_svg_generator_spec.rb delete mode 100644 spec/suspenders/generators/json_generator_spec.rb delete mode 100644 spec/suspenders/generators/lint_generator_spec.rb delete mode 100644 spec/suspenders/generators/production/compression_generator_spec.rb delete mode 100644 spec/suspenders/generators/production/deployment_generator_spec.rb delete mode 100644 spec/suspenders/generators/production/email_generator_spec.rb delete mode 100644 spec/suspenders/generators/production/manifest_generator_spec.rb delete mode 100644 spec/suspenders/generators/production/single_redirect_spec.rb delete mode 100644 spec/suspenders/generators/profiler_generator_spec.rb delete mode 100644 spec/suspenders/generators/runner_generator_spec.rb delete mode 100644 spec/suspenders/generators/staging/pull_requests_generator_spec.rb delete mode 100644 spec/suspenders/generators/static_generator_spec.rb delete mode 100644 spec/suspenders/generators/stylelint_generator_spec.rb delete mode 100644 templates/Gemfile.erb delete mode 100644 templates/Procfile delete mode 100644 templates/README.md.erb delete mode 100644 templates/_analytics.html.erb delete mode 100644 templates/_css_overrides.html.erb delete mode 100644 templates/_flashes.html.erb delete mode 100644 templates/action_mailer.rb delete mode 100644 templates/active_job.rb delete mode 100644 templates/application.postcss.css delete mode 100755 templates/bin_auto_migrate delete mode 100755 templates/bin_deploy delete mode 100644 templates/bin_setup delete mode 100644 templates/bin_setup_review_app.erb delete mode 100755 templates/bin_yarn delete mode 100644 templates/bundler_audit.rake delete mode 100644 templates/chromedriver.rb delete mode 100644 templates/circle.yml.erb delete mode 100644 templates/config_locales_en.yml.erb delete mode 100644 templates/descriptions/advisories.md delete mode 100644 templates/descriptions/analytics.md delete mode 100644 templates/descriptions/ci.md delete mode 100644 templates/descriptions/compression.md delete mode 100644 templates/descriptions/db_optimizations.md delete mode 100644 templates/descriptions/deployment.md delete mode 100644 templates/descriptions/email.md delete mode 100644 templates/descriptions/factories.md delete mode 100644 templates/descriptions/force_tls.md delete mode 100644 templates/descriptions/forms.md delete mode 100644 templates/descriptions/inline_svg.md delete mode 100644 templates/descriptions/jobs.md delete mode 100644 templates/descriptions/js_driver.md delete mode 100644 templates/descriptions/json.md delete mode 100644 templates/descriptions/lint.md delete mode 100644 templates/descriptions/manifest.md delete mode 100644 templates/descriptions/profiler.md delete mode 100644 templates/descriptions/pull_requests.md delete mode 100644 templates/descriptions/runner.md delete mode 100644 templates/descriptions/single_redirect.md delete mode 100644 templates/descriptions/static.md delete mode 100644 templates/descriptions/stylelint.md delete mode 100644 templates/descriptions/stylesheet_base.md delete mode 100644 templates/descriptions/testing.md delete mode 100644 templates/descriptions/timeout.md delete mode 100644 templates/descriptions/views.md delete mode 100644 templates/dev.rake delete mode 100644 templates/email.rb delete mode 100644 templates/errors.rb delete mode 100644 templates/factories.rb delete mode 100644 templates/factory_bot_rspec.rb delete mode 100644 templates/flashes_helper.rb delete mode 100644 templates/hound.yml delete mode 100644 templates/i18n.rb delete mode 100644 templates/inline_svg.rb delete mode 100644 templates/json_encoding.rb delete mode 100644 templates/oj.rb delete mode 100644 templates/partials/ci_simplecov.rb delete mode 100644 templates/partials/db_optimizations_configuration.rb delete mode 100644 templates/partials/deployment_readme.md delete mode 100644 templates/partials/email_smtp.rb delete mode 100644 templates/partials/profiler_readme.md delete mode 100644 templates/partials/pull_requests_config.rb delete mode 100644 templates/partials/runner_readme.md delete mode 100644 templates/partials/runner_setup.rb delete mode 100644 templates/postcss.config.js delete mode 100644 templates/postgresql_database.yml.erb delete mode 100644 templates/rack_mini_profiler.rb delete mode 100644 templates/rails_helper.rb delete mode 100644 templates/sample_env delete mode 100644 templates/secrets.yml delete mode 100644 templates/shoulda_matchers_config_rspec.rb delete mode 100644 templates/smtp.rb delete mode 100644 templates/spec_helper.rb delete mode 100644 templates/stylelintrc.json delete mode 100644 templates/suspenders_gitignore delete mode 100644 templates/suspenders_layout.html.erb.erb create mode 100644 test/dummy/Rakefile rename spec/support/bundler_stub.rb => test/dummy/app/assets/images/.keep (100%) create mode 100644 test/dummy/app/assets/stylesheets/application.css create mode 100644 test/dummy/app/channels/application_cable/channel.rb create mode 100644 test/dummy/app/channels/application_cable/connection.rb create mode 100644 test/dummy/app/controllers/application_controller.rb create mode 100644 test/dummy/app/controllers/concerns/.keep create mode 100644 test/dummy/app/helpers/application_helper.rb create mode 100644 test/dummy/app/jobs/application_job.rb create mode 100644 test/dummy/app/mailers/application_mailer.rb create mode 100644 test/dummy/app/models/application_record.rb create mode 100644 test/dummy/app/models/concerns/.keep create mode 100644 test/dummy/app/views/layouts/application.html.erb create mode 100644 test/dummy/app/views/layouts/mailer.html.erb create mode 100644 test/dummy/app/views/layouts/mailer.text.erb create mode 100755 test/dummy/bin/rails create mode 100755 test/dummy/bin/rake create mode 100755 test/dummy/bin/setup create mode 100644 test/dummy/config.ru create mode 100644 test/dummy/config/application.rb create mode 100644 test/dummy/config/boot.rb create mode 100644 test/dummy/config/cable.yml create mode 100644 test/dummy/config/database.yml create mode 100644 test/dummy/config/environment.rb create mode 100644 test/dummy/config/environments/development.rb create mode 100644 test/dummy/config/environments/production.rb create mode 100644 test/dummy/config/environments/test.rb create mode 100644 test/dummy/config/initializers/content_security_policy.rb create mode 100644 test/dummy/config/initializers/filter_parameter_logging.rb create mode 100644 test/dummy/config/initializers/inflections.rb create mode 100644 test/dummy/config/initializers/permissions_policy.rb create mode 100644 test/dummy/config/locales/en.yml create mode 100644 test/dummy/config/puma.rb create mode 100644 test/dummy/config/routes.rb create mode 100644 test/dummy/config/storage.yml create mode 100644 test/dummy/lib/assets/.keep create mode 100644 test/dummy/log/.keep create mode 100644 test/dummy/public/404.html create mode 100644 test/dummy/public/422.html create mode 100644 test/dummy/public/500.html create mode 100644 test/dummy/public/apple-touch-icon-precomposed.png create mode 100644 test/dummy/public/apple-touch-icon.png create mode 100644 test/dummy/public/favicon.ico create mode 100644 test/dummy/storage/.keep create mode 100644 test/dummy/tmp/.keep create mode 100644 test/dummy/tmp/pids/.keep create mode 100644 test/dummy/tmp/storage/.keep create mode 100644 test/suspenders_test.rb create mode 100644 test/test_helper.rb diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56c4a64e2..1656b7503 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,55 +1,28 @@ name: CI on: - workflow_dispatch: push: branches: - main + pull_request: - paths-ignore: - - 'docs/**' - - '**.md' jobs: - test: - + build: runs-on: ubuntu-latest - - services: - postgres: - image: postgres - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 + name: Ruby ${{ matrix.ruby }} + strategy: + matrix: + ruby: + - '3.1.4' + - '3.2.2' steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Set git configuration - run: | - git config --global init.defaultBranch main - git config --global user.name 'GitHub Actions' - git config --global user.email 'microsoft@example.com' - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - bundler-cache: false - - - name: Install dependencies - run: bundle install - - - name: Run tests - run: bin/rake - env: - DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/dummy_app_test" - DEBUG: 1 - SPEC_OPTS: "--no-color -f d" + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run the default task + run: bundle exec rake diff --git a/.gitignore b/.gitignore index 3ab24ac39..a3ee5aad3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,10 @@ -*.gem -*.swp -Gemfile.lock -/.bundle -/tmp +/.bundle/ +/doc/ +/log/*.log +/pkg/ +/tmp/ +/test/dummy/db/*.sqlite3 +/test/dummy/db/*.sqlite3-* +/test/dummy/log/*.log +/test/dummy/storage/ +/test/dummy/tmp/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1b9ab5e8..1461e92ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,59 +1,55 @@ # Contributing -We love pull requests from everyone. By participating in this project, you -agree to abide by the thoughtbot [code of conduct]. +We love contributions from everyone. +By participating in this project, +you agree to abide by the thoughtbot [code of conduct]. -[code of conduct]: https://thoughtbot.com/open-source-code-of-conduct + [code of conduct]: https://thoughtbot.com/open-source-code-of-conduct -Fork the repo: +We expect everyone to follow the code of conduct +anywhere in thoughtbot's project codebases, +issue trackers, chatrooms, and mailing lists. - git clone git@github.com:thoughtbot/suspenders.git +## Contributing Code -Set up your machine: +Fork the repo. - ./bin/setup +Run the setup script. -Make sure the tests pass: - - rake - -Make your change. Write tests. Follow our [style guide][style]. Make the tests -pass: - -[style]: https://github.com/thoughtbot/guides/blob/main/ruby/README.md - - rake - -Mention how your changes affect the project to other developers and users in -the `NEWS.md` file. +``` +./bin/setup +``` -Write a [good commit message][commit]. -Push to your fork. -[Submit a pull request][pr]. +Make sure the tests pass: -[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html -[pr]: https://github.com/thoughtbot/suspenders/compare/ +``` +bundle exec rake +``` -If [Hound] catches style violations, fix them. +Make your change, with new passing tests. Follow the [style guide][style]. -[hound]: https://houndci.com + [style]: https://github.com/thoughtbot/guides/tree/master/style -Wait for us. We try to at least comment on pull requests within one business -day. We may suggest changes. +Mention how your changes affect the project to other developers and users in the +`NEWS.md` file. -## Generators +Push to your fork. Write a [good commit message][commit]. Submit a pull request. -All new contributions must be within the generator framework, as described in -[our goals](GOALS.md). + [commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html -## Versions +Others will give constructive feedback. +This is a time for discussion and improvements, +and making the necessary changes will be required before we can +merge the contribution. -To update the Ruby version, change `.ruby-version`. +## Publishing to RubyGems -If you see this error while running tests: +When the gem is ready to be shared as a formal release, it can be +[published][published] to RubyGems. -``` -Your Ruby version is XXX, but your Gemfile specified YYY (Bundler::RubyVersionMismatch) -``` + [published]: https://guides.rubyonrails.org/plugins.html#publishing-your-gem -Try removing the `tmp/` directory and re-running the tests. +1. Bump the version number in `Suspenders::VERSION` +2. Run `bundle exec rake build` +3. Run `bundle exec rake install` +4. Run `bundle exec rake release` diff --git a/Gemfile b/Gemfile index b4e2a20bb..568862459 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,12 @@ source "https://rubygems.org" +git_source(:github) { |repo| "https://github.com/#{repo}.git" } +# Specify your gem's dependencies in suspenders.gemspec. gemspec + +gem "puma" + +gem "sqlite3" + +# Start debugger with binding.b [https://github.com/ruby/debug] +# gem "debug", ">= 1.0.0" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..4ed84d85c --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,241 @@ +PATH + remote: . + specs: + suspenders (3.0.0) + rails (~> 7.0) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.1.1) + actionpack (= 7.1.1) + activesupport (= 7.1.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (7.1.1) + actionpack (= 7.1.1) + activejob (= 7.1.1) + activerecord (= 7.1.1) + activestorage (= 7.1.1) + activesupport (= 7.1.1) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.1.1) + actionpack (= 7.1.1) + actionview (= 7.1.1) + activejob (= 7.1.1) + activesupport (= 7.1.1) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.2) + actionpack (7.1.1) + actionview (= 7.1.1) + activesupport (= 7.1.1) + nokogiri (>= 1.8.5) + rack (>= 2.2.4) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.1) + actionpack (= 7.1.1) + activerecord (= 7.1.1) + activestorage (= 7.1.1) + activesupport (= 7.1.1) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.1.1) + activesupport (= 7.1.1) + builder (~> 3.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.1) + activesupport (= 7.1.1) + globalid (>= 0.3.6) + activemodel (7.1.1) + activesupport (= 7.1.1) + activerecord (7.1.1) + activemodel (= 7.1.1) + activesupport (= 7.1.1) + timeout (>= 0.4.0) + activestorage (7.1.1) + actionpack (= 7.1.1) + activejob (= 7.1.1) + activerecord (= 7.1.1) + activesupport (= 7.1.1) + marcel (~> 1.0) + activesupport (7.1.1) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + ast (2.4.2) + base64 (0.1.1) + bigdecimal (3.1.4) + builder (3.2.4) + concurrent-ruby (1.2.2) + connection_pool (2.4.1) + crass (1.0.6) + date (3.3.3) + drb (2.1.1) + ruby2_keywords + erubi (1.12.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + io-console (0.6.0) + irb (1.8.3) + rdoc + reline (>= 0.3.8) + json (2.6.3) + language_server-protocol (3.17.0.3) + lint_roller (1.1.0) + loofah (2.21.4) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + mini_mime (1.1.5) + minitest (5.20.0) + mutex_m (0.1.2) + net-imap (0.4.1) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.4.0) + net-protocol + nio4r (2.5.9) + nokogiri (1.15.4-arm64-darwin) + racc (~> 1.4) + nokogiri (1.15.4-x86_64-linux) + racc (~> 1.4) + parallel (1.23.0) + parser (3.2.2.4) + ast (~> 2.4.1) + racc + psych (5.1.1.1) + stringio + puma (6.4.0) + nio4r (~> 2.0) + racc (1.7.1) + rack (3.0.8) + rack-session (2.0.0) + rack (>= 3.0.0) + rack-test (2.1.0) + rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.1) + actioncable (= 7.1.1) + actionmailbox (= 7.1.1) + actionmailer (= 7.1.1) + actionpack (= 7.1.1) + actiontext (= 7.1.1) + actionview (= 7.1.1) + activejob (= 7.1.1) + activemodel (= 7.1.1) + activerecord (= 7.1.1) + activestorage (= 7.1.1) + activesupport (= 7.1.1) + bundler (>= 1.15.0) + railties (= 7.1.1) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.1.1) + actionpack (= 7.1.1) + activesupport (= 7.1.1) + irb + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) + rainbow (3.1.1) + rake (13.0.6) + rdoc (6.5.0) + psych (>= 4.0.0) + regexp_parser (2.8.2) + reline (0.3.9) + io-console (~> 0.5) + rexml (3.2.6) + rubocop (1.56.4) + base64 (~> 0.1.1) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.3) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.29.0) + parser (>= 3.2.1.0) + rubocop-performance (1.19.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) + sqlite3 (1.6.7-arm64-darwin) + sqlite3 (1.6.7-x86_64-linux) + standard (1.31.2) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.56.4) + standard-custom (~> 1.0.0) + standard-performance (~> 1.2) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.2.1) + lint_roller (~> 1.1) + rubocop-performance (~> 1.19.1) + stringio (3.0.8) + thor (1.2.2) + timeout (0.4.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + webrick (1.8.1) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.6.12) + +PLATFORMS + arm64-darwin-21 + x86_64-linux + +DEPENDENCIES + puma + sqlite3 + standard + suspenders! + +BUNDLED WITH + 2.4.19 diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 000000000..eb5a954de --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright Steve Polito + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 294501a8c..5a9e7f9f9 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,56 @@ # Suspenders -[![Build Status](https://github.com/thoughtbot/suspenders/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/thoughtbot/suspenders/actions) -[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) - -Suspenders is the base Rails application used at -[thoughtbot](https://thoughtbot.com/). - - ![Suspenders boy](http://media.tumblr.com/1TEAMALpseh5xzf0Jt6bcwSMo1_400.png) - -## Installation - -First install the suspenders gem: - - gem install suspenders - -Then run: - - suspenders projectname - -This will create a Rails app in `projectname` using the latest version of Rails. - -### Associated services - -* Enable [Circle CI](https://circleci.com/) Continuous Integration -* Enable [GitHub auto deploys to Heroku staging and review - apps](https://dashboard.heroku.com/apps/app-name-staging/deploy/github). - -## Gemfile - -To see the latest and greatest gems, look at Suspenders' -[Gemfile](templates/Gemfile.erb), which will be appended to the default -generated projectname/Gemfile. - -It includes application gems like: - -* [Sidekiq](https://github.com/mperham/sidekiq) for background - processing -* [High Voltage](https://github.com/thoughtbot/high_voltage) for static pages -* [Honeybadger](https://www.honeybadger.io/?affiliate=A43uwl) for exception notification -* [Oj](http://www.ohler.com/oj/) -* [Postgres](https://github.com/ged/ruby-pg) for access to the Postgres database -* [Rack Canonical Host](https://github.com/tylerhunt/rack-canonical-host) to - ensure all requests are served from the same domain -* [Rack Timeout](https://github.com/heroku/rack-timeout) to abort requests that are - taking too long -* [Recipient Interceptor](https://github.com/croaky/recipient_interceptor) to - avoid accidentally sending emails to real people from staging -* [Simple Form](https://github.com/plataformatec/simple_form) for form markup - and style -* [Skylight](https://www.skylight.io/) for monitoring performance -* [Title](https://github.com/calebthompson/title) for storing titles in - translations - -And development gems like: +Suspenders is a Rails plugin containing generators for configuring Rails +applications. It is used by thoughtbot to get a jump start on a new or existing +app. Use Suspenders if you're in a rush to build something amazing; don't use it +if you like missing deadlines. -* [Dotenv](https://github.com/bkeepers/dotenv) for loading environment variables -* [Pry Rails](https://github.com/rweng/pry-rails) for interactively exploring - objects -* [ByeBug](https://github.com/deivid-rodriguez/byebug) for interactively - debugging behavior -* [Bullet](https://github.com/flyerhzm/bullet) for help to kill N+1 queries and - unused eager loading -* [Bundler Audit](https://github.com/rubysec/bundler-audit) for scanning the - Gemfile for insecure dependencies based on published CVEs -* [Web Console](https://github.com/rails/web-console) for better debugging via - in-browser IRB consoles. +![Suspenders boy](http://media.tumblr.com/1TEAMALpseh5xzf0Jt6bcwSMo1_400.png) -And testing gems like: +## Usage -* [Capybara](https://github.com/jnicklas/capybara) and - [Google Chromedriver] - integration testing -* [capybara_accessibility_audit](https://github.com/thoughtbot/capybara_accessibility_audit) and - [capybara_accessible_selectors](https://github.com/citizensadvice/capybara_accessible_selectors) -* [Factory Bot](https://github.com/thoughtbot/factory_bot) for test data -* [Formulaic](https://github.com/thoughtbot/formulaic) for integration testing - HTML forms -* [RSpec](https://github.com/rspec/rspec) for unit testing -* [RSpec Mocks](https://github.com/rspec/rspec-mocks) for stubbing and spying -* [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for common - RSpec matchers +``` +group :development, :test do + gem "suspenders" +end +``` -## Other goodies +``` +./bin/rails suspenders g all +``` -Suspenders also comes with: +## Generators -* The [`./bin/setup`][setup] convention for new developer setup -* The `./bin/deploy` convention for deploying to Heroku -* Rails' flashes set up and in application layout -* A few nice time formats set up for localization -* `Rack::Deflater` to [compress responses with Gzip][compress] -* A [low database connection pool limit][pool] -* [Safe binstubs][binstub] -* [t() and l() in specs without prefixing with I18n][i18n] -* An automatically-created `SECRET_KEY_BASE` environment variable in all - environments -* Configuration for [CircleCI][circle] Continuous Integration (tests) -* Configuration for [Hound][hound] Continuous Integration (style) -* Configuration for [stylelint][stylelint] -* The analytics adapter [Segment][segment] (and therefore config for Google - Analytics, Intercom, Facebook Ads, Twitter Ads, etc.) -* [PostCSS Autoprefixer][autoprefixer] for CSS vendor prefixes -* [PostCSS Normalize][normalize] for resetting browser styles - -[setup]: https://robots.thoughtbot.com/bin-setup -[compress]: https://robots.thoughtbot.com/content-compression-with-rack-deflater -[pool]: https://devcenter.heroku.com/articles/concurrency-and-database-connections -[binstub]: https://github.com/thoughtbot/suspenders/pull/282 -[i18n]: https://github.com/thoughtbot/suspenders/pull/304 -[circle]: https://circleci.com/docs -[hound]: https://houndci.com -[stylelint]: https://stylelint.io/ -[segment]: https://segment.com -[autoprefixer]: https://github.com/postcss/autoprefixer -[normalize]: https://github.com/csstools/postcss-normalize - -## Heroku - -Read the documentation on [deploying to Heroku][heroku deploy] - -You can optionally create Heroku staging and production apps: - - suspenders app --heroku true - -This: - -* Creates a staging and production Heroku app -* Sets them as `staging` and `production` Git remotes -* Configures staging with `HONEYBADGER_ENV` environment variable set - to `staging` -* Creates a [Heroku Pipeline] for review apps -* Schedules automated backups for 10AM UTC for both `staging` and `production` - -[Heroku Pipeline]: https://devcenter.heroku.com/articles/pipelines -[heroku deploy]: https://github.com/thoughtbot/suspenders/blob/master/docs/heroku_deploy.md - -You can optionally specify alternate Heroku flags: - - suspenders app \ - --heroku true \ - --heroku-flags "--region eu --addons sendgrid,ssl" - -See all possible Heroku flags: - - heroku help create - -## Git - -This will initialize a new git repository for your Rails app. You can -bypass this with the `--skip-git` option: - - suspenders app --skip-git true - -## GitHub - -You can optionally create a GitHub repository for the suspended Rails app. It -requires that you have [Hub](https://github.com/github/hub) on your system: - - brew install hub # macOS, for other systems see https://github.com/github/hub#installation - suspenders app --github organization/project - -This has the same effect as running: - - hub create organization/project - -## Dependencies - -Suspenders requires the latest version of Ruby. - -Some gems included in Suspenders have native extensions. You should have GCC -installed on your machine before generating an app with Suspenders. - -Use [OS X GCC Installer](https://github.com/kennethreitz/osx-gcc-installer/) for -Snow Leopard (OS X 10.6). - -Use [Command Line Tools for Xcode](https://developer.apple.com/downloads/index.action) -for Lion (OS X 10.7) or Mountain Lion (OS X 10.8). - -We use [Google Chromedriver] for full-stack JavaScript integration testing. It -requires Google Chrome or Chromium. - -[Google Chromedriver]: https://sites.google.com/a/chromium.org/chromedriver/home - -PostgreSQL needs to be installed and running for the `db:create` rake task. - -Redis needs to be installed and running for Sidekiq - -## Issues - -If you have problems, please create a -[GitHub Issue](https://github.com/thoughtbot/suspenders/issues). +TODO ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md). - +See the [CONTRIBUTING] document. Thank you, [contributors]! -[contributors]: https://github.com/thoughtbot/suspenders/graphs/contributors + [CONTRIBUTING]: CONTRIBUTING.md + [contributors]: https://github.com/thoughtbot/suspenders/graphs/contributors ## License -Suspenders is Copyright © 2008-2017 thoughtbot. -It is free software, -and may be redistributed under the terms specified in the [LICENSE] file. +Suspenders is Copyright (c) thoughtbot, inc. +It is free software, and may be redistributed +under the terms specified in the [LICENSE] file. + + [LICENSE]: /LICENSE -[LICENSE]: LICENSE +## About -## About thoughtbot +Suspenders is maintained by [thoughtbot]. -[![thoughtbot][thoughtbot-logo]][thoughtbot] +![thoughtbot](https://thoughtbot.com/brand_assets/93:44.svg) Suspenders is maintained and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc. We love open source software! -See [our other projects][community]. -We are [available for hire][hire]. +See [our other projects][community] +or [hire us][hire] to help build your product. -[thoughtbot]: https://thoughtbot.com?utm_source=github -[thoughtbot-logo]: https://thoughtbot.com/brand_assets/93:44.svg -[community]: https://thoughtbot.com/community?utm_source=github -[hire]: https://thoughtbot.com?utm_source=github + [community]: https://thoughtbot.com/community?utm_source=github + [hire]: https://thoughtbot.com/hire-us?utm_source=github diff --git a/Rakefile b/Rakefile index 13e2cc25d..0e36eba94 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,13 @@ require "bundler/setup" require "bundler/gem_tasks" -require "rspec/core/rake_task" +require "minitest/test_task" require "standard/rake" -RSpec::Core::RakeTask.new(:rspec) +Minitest::TestTask.create(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.warning = false + t.test_globs = ["test/**/*_test.rb"] +end -desc "Run the test suite" -task default: [:rspec, :standard] +task default: %i[test standard] diff --git a/USAGE b/USAGE deleted file mode 100644 index 298bb7580..000000000 --- a/USAGE +++ /dev/null @@ -1,13 +0,0 @@ -Description: - Suspenders is a Rails template with thoughtbot standard - defaults, ready to deploy to Heroku. - - For full details on the changes we've made compared to - a vanilla Rails app, check our GitHub project: - https://github.com/thoughtbot/suspenders - -Example: - suspenders ~/Code/weblog - - This generates a Rails installation in ~/Code/weblog configured - with our preferred defaults. diff --git a/bin/rake b/bin/rake deleted file mode 100755 index 26c7a2d5b..000000000 --- a/bin/rake +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by Bundler. -# -# The application 'rake' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'pathname' -ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require 'rubygems' -require 'bundler/setup' - -load Gem.bin_path('rake', 'rake') diff --git a/bin/rspec b/bin/rspec deleted file mode 100755 index 0c86b5c6f..000000000 --- a/bin/rspec +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by Bundler. -# -# The application 'rspec' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'pathname' -ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require 'rubygems' -require 'bundler/setup' - -load Gem.bin_path('rspec-core', 'rspec') diff --git a/bin/setup b/bin/setup index 9e6d7684b..cf4ad25e1 100755 --- a/bin/setup +++ b/bin/setup @@ -1,13 +1,6 @@ -#!/bin/sh +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx -# Run this script immediately after cloning the codebase. - -# Exit if any subcommand fails -set -e - -# Set up Ruby dependencies via Bundler bundle install - -# Add binstubs to PATH in ~/.zshenv like this: -# export PATH=".git/safe/../../bin:$PATH" -mkdir -p .git/safe diff --git a/bin/suspenders b/bin/suspenders deleted file mode 100755 index 700ab6bcb..000000000 --- a/bin/suspenders +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env ruby -require 'pathname' - -source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path -$LOAD_PATH << source_path - -require "suspenders/version" - -ruby_version_range = Suspenders::RUBY_VERSION_RANGE.map do |version| - Gem::Version.new(version) -end - -current_ruby_version = Gem::Version.new(RUBY_VERSION) - -unless current_ruby_version.between?(*ruby_version_range) - abort "Your version of Ruby #{current_ruby_version} is not supported. " \ - "Versions from #{ruby_version_range.map(&:to_s).join(" to ")} are supported." -end - -activate_rails_version = ->(rails_version) do - rails_bin_path = Gem.activate_bin_path("railties", "rails", rails_version) - rails_path = File.expand_path("../..", rails_bin_path) - $LOAD_PATH.unshift(rails_path) -end - -if str = ARGV.first - str = str.b[/\A_(.*)_\z/, 1] - - if str && Gem::Version.correct?(str) - rails_version = str - ARGV.shift - - begin - activate_rails_version.call(rails_version) - rescue Gem::GemNotFoundException - abort "Suspenders error: Unable to find Rails version #{rails_version}" - end - else - require "suspenders/version" - - spec = Gem::Specification.find_by_name("rails", Suspenders::RAILS_VERSION) - - activate_rails_version.call(spec.version.to_s) - end -end - -require "suspenders" - -if ARGV.empty? - puts "Please provide a path for the new application" - puts - puts "See --help for more info" - exit 0 -elsif ["-v", "--version"].include? ARGV[0] - puts Suspenders::VERSION - exit 0 -end - -templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__)) -Suspenders::AppGenerator.source_root templates_root -Suspenders::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root - -Suspenders::AppGenerator.start diff --git a/bin/test b/bin/test new file mode 100755 index 000000000..5516a12bc --- /dev/null +++ b/bin/test @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +$: << File.expand_path("../test", __dir__) + +require "bundler/setup" +require "rails/plugin/test" diff --git a/docs/heroku_deploy.md b/docs/heroku_deploy.md deleted file mode 100644 index 082224158..000000000 --- a/docs/heroku_deploy.md +++ /dev/null @@ -1,19 +0,0 @@ -# Deploying to Heroku - -## Setup - -Deploying to Heroku requires two additional steps: - -1. Set the following environment variables: - -- `ASSET_HOST`: `siteURL.herokuapp.com` -- `APPLICATION_HOST`: `siteURL.herokuapp.com` -- `SMTP_ADDRESS`: `smtp.example.com` -- `SMTP_DOMAIN`: `example.com` -- `SMTP_USERNAME`: `username` -- `SMTP_PASSWORD`: `password` -- `AUTO_MIGRATE_DB`: `true` - -## Execution - -- Use the `./bin/deploy` convention for deploying to Heroku diff --git a/docs/rails_7.md b/docs/rails_7.md deleted file mode 100644 index dee877ff2..000000000 --- a/docs/rails_7.md +++ /dev/null @@ -1,5 +0,0 @@ -# Rails 7 - -To create a new Rails 7 app with Suspenders, you need to have `node >= 14.6`. - -After the app is created, run the server with `bin/dev`. diff --git a/lib/suspenders.rb b/lib/suspenders.rb index 9fb799444..6f8c7b5d2 100644 --- a/lib/suspenders.rb +++ b/lib/suspenders.rb @@ -1,34 +1,6 @@ require "suspenders/version" -require "suspenders/exit_on_failure" -require "suspenders/generators/accessibility_generator" -require "suspenders/generators/advisories_generator" -require "suspenders/generators/app_generator" -require "suspenders/generators/static_generator" -require "suspenders/generators/stylesheet_base_generator" -require "suspenders/generators/stylelint_generator" -require "suspenders/generators/forms_generator" -require "suspenders/generators/ci_generator" -require "suspenders/generators/db_optimizations_generator" -require "suspenders/generators/factories_generator" -require "suspenders/generators/lint_generator" -require "suspenders/generators/jobs_generator" -require "suspenders/generators/analytics_generator" -require "suspenders/generators/views_generator" -require "suspenders/generators/js_driver_generator" -require "suspenders/generators/json_generator" -require "suspenders/generators/testing_generator" -require "suspenders/generators/inline_svg_generator" -require "suspenders/generators/profiler_generator" -require "suspenders/generators/runner_generator" -require "suspenders/generators/production/force_tls_generator" -require "suspenders/generators/production/compression_generator" -require "suspenders/generators/production/email_generator" -require "suspenders/generators/production/timeout_generator" -require "suspenders/generators/production/deployment_generator" -require "suspenders/generators/production/manifest_generator" -require "suspenders/generators/production/single_redirect" -require "suspenders/generators/staging/pull_requests_generator" -require "suspenders/actions" -require "suspenders/actions/strip_comments_action" -require "suspenders/adapters/heroku" -require "suspenders/app_builder" +require "suspenders/railtie" + +module Suspenders + # Your code goes here... +end diff --git a/lib/suspenders/actions.rb b/lib/suspenders/actions.rb deleted file mode 100644 index 0ad26183c..000000000 --- a/lib/suspenders/actions.rb +++ /dev/null @@ -1,106 +0,0 @@ -module Suspenders - module Actions - def replace_in_file(relative_path, find, replace) - path = File.join(destination_root, relative_path) - contents = IO.read(path) - unless contents.gsub!(find, replace) - raise "#{find.inspect} not found in #{relative_path}" - end - File.write(path, contents) - end - - def action_mailer_host(rails_env, host) - config = "config.action_mailer.default_url_options = { host: #{host} }" - configure_environment(rails_env, config) - end - - def action_mailer_asset_host(rails_env, host) - config = "config.action_mailer.asset_host = #{host}" - configure_environment(rails_env, config) - end - - def configure_environment(rails_env, config) - inject_into_file( - "config/environments/#{rails_env}.rb", - "\n #{config}", - before: "\nend" - ) - end - - def expand_json(file, data) - action ExpandJson.new(destination_root, file, data) - end - - def gem(*args) - options = args.extract_options! - name, *versions = args - - parts = [quote(name)] - - if (versions = versions.any? ? versions : options.delete(:version)) - versions = Array(versions) - versions.each do |version| - parts << quote(version) - end - end - - parts << quote(options) unless options.empty? - - str = [] - str << indentation - str << "gem #{parts.join(", ")}" - append_file "Gemfile", %(\n#{str.join}\n), verbose: false - end - - class ExpandJson - def initialize(destination_root, file, data) - @destination_root = destination_root - @file = file - @data = data - end - - def invoke! - write_out { |existing_json| existing_json.deep_merge(data) } - end - - def revoke! - write_out { |existing_json| hash_unmerge(existing_json, data) } - end - - private - - attr_reader :destination_root, :file, :data - - def write_out - new_json = yield(existing_json) - IO.write(destination_file, JSON.pretty_generate(new_json)) - end - - def destination_file - File.join(destination_root, file) - end - - def existing_json - JSON.parse(IO.read(destination_file), symbolize_names: true) - rescue Errno::ENOENT - {} - end - - def hash_unmerge(hash, subhash) - subhash.reduce(hash) do |acc, (k, v)| - if hash.has_key?(k) - if v == hash[k] - acc.except(k) - elsif v.is_a?(Hash) - acc.merge(k => hash_unmerge(hash[k], v)) - else - acc - end - else - acc - end - end - end - end - end -end diff --git a/lib/suspenders/actions/strip_comments_action.rb b/lib/suspenders/actions/strip_comments_action.rb deleted file mode 100644 index 3abb37fd6..000000000 --- a/lib/suspenders/actions/strip_comments_action.rb +++ /dev/null @@ -1,254 +0,0 @@ -require "parser/current" - -module Suspenders - module Actions - class StripCommentsAction - class << self - def call(source) - parser = Parser::CurrentRuby.new - - source - .then { |s| strip_comments(s, parser) } - .then { |s| strip_trailing_whitespace(s) } - .then { |s| strip_dup_newlines(s) } - .then { |s| strip_leading_scope_newlines(s, parser) } - end - - private - - def strip_comments(source, parser) - StripComments.call(source, parser.reset) - end - - def strip_trailing_whitespace(source) - source.gsub(/[[:blank:]]+$/, "") - end - - def strip_dup_newlines(source) - source.gsub(/\n{2,}/, "\n\n") - end - - def strip_leading_scope_newlines(source, parser) - StripLeadingScopeNewlines.call(source, parser.reset) - end - end - - # Strips full-line and inline comments from a buffer but does - # not remove whitespaces or newlines after the fact. Example - # input: - # - # MyGem.application.configure do |config| - # # Full-line comment - # config.option1 = :value # Inline comment - # end - # - # The output is: - # - # MyGem.application.configure do |config| - # - # config.option1 = :value - # end - class StripComments - class << self - def call(source, parser) - buffer = Parser::Source::Buffer.new(nil, source: source) - rewriter = Parser::Source::TreeRewriter.new(buffer) - - _, comments = parser.parse_with_comments(buffer) - - comments.each do |comment| - strip_comment(comment, buffer, rewriter) - end - - rewriter.process - end - - private - - def strip_comment(comment, buffer, rewriter) - expr = comment.location.expression - - if full_line_comment?(expr) - expr = full_line_comment_expr(expr, buffer) - end - - rewriter.remove(expr) - end - - def full_line_comment_expr(expr, buffer) - pos = BackwardStringScanner.beginning_of_line_pos(expr, expr.begin_pos) - - Parser::Source::Range.new(buffer, pos, expr.end_pos + 1) - end - - def full_line_comment?(expr) - expr.source == expr.source_line.lstrip - end - end - end - - # A tiny, non-stateful backward string scanner somewhat inspired - # by Ruby's StringScanner. Ruby's StringScanner is unable to - # seek backward on a string. - class BackwardStringScanner - def self.beginning_of_line_pos(expr, initial_pos) - skip_before(expr, initial_pos) { |char| char == "\n" } - end - - def self.skip_before(expr, initial_pos, &block) - skip_until(expr, initial_pos, -1, &block) - end - - def self.skip_until(expr, initial_pos, lookup_inc = 0) - pos = initial_pos - - loop do - break if pos.zero? - char = expr.source_buffer.source[pos + lookup_inc] - break if yield(char) - pos -= 1 - end - - pos - end - end - - # The intent of this class is purely aesthetic: remove leading - # newlines inside of code scopes like blocks and begin/end. - # Example input: - # - # module MyGem - # - # MyGem.application.configure do |config| - # - # config.option1 = true - # - # config.option2 = false - # end - # end - # - # The output is: - # - # module MyGem - # MyGem.application.configure do |config| - # config.option1 = true - # - # config.option2 = false - # end - # end - class StripLeadingScopeNewlines - def self.call(source, parser) - buffer = Parser::Source::Buffer.new(nil, source: source) - ast = parser.parse(buffer) - - LeadingNewlineStripRewriter.new.rewrite(buffer, ast).lstrip - end - - class LeadingNewlineStripRewriter < Parser::TreeRewriter - def on_module(node) - strip_newline_before(node.children[1]) - strip_newline_after(node.children.last) - - super - end - - def on_class(node) - strip_newline_before(node.children[2]) - strip_newline_after(node.children.last) - - super - end - - def on_begin(node) - handle_begin(node) - - super - end - - def on_kwbegin(node) - strip_newline_before(node.children[0]) - strip_newline_after(node.children.last) - - handle_begin(node) - - super - end - - def on_block(node) - strip_newline_before(node.children[2]) - strip_newline_after(node.children.last) - - super - end - - private - - def handle_begin(node) - strip_blank_lines_between_setter_calls(node.children) - - node.children.each do |child_node| - send("on_#{child_node.type}", child_node) - end - end - - def strip_blank_lines_between_setter_calls(children) - pairs = children.each_cons(2).to_a - - pairs.each do |(node_before, node_after)| - if setter_call?(node_before) && setter_call?(node_after) - strip_newline_before(node_after) - end - end - end - - def setter_call?(node) - node.children[1].to_s.end_with?("=") - end - - def strip_newline_before(node) - return if node.nil? - - expr = node.location.expression - end_pos = find_end_pos(expr, expr.begin_pos) - begin_pos = find_begin_pos(expr, end_pos) - - strip_source_range(expr, begin_pos, end_pos) - end - - def strip_newline_after(node) - return if node.nil? - - expr = node.location.expression - source = expr.source_buffer.source - - if source[expr.end_pos + 1] == "\n" - strip_source_range(expr, expr.end_pos, expr.end_pos + 1) - end - end - - def find_end_pos(expr, begin_pos) - BackwardStringScanner.skip_until(expr, begin_pos) do |char| - char == "\n" - end - end - - def find_begin_pos(expr, end_pos) - BackwardStringScanner.skip_before(expr, end_pos) do |char| - char != "\n" && char != " " - end - end - - def strip_source_range(expr, begin_pos, end_pos) - remove( - Parser::Source::Range.new( - expr.source_buffer, - begin_pos, - end_pos - ) - ) - end - end - end - end - end -end diff --git a/lib/suspenders/adapters/heroku.rb b/lib/suspenders/adapters/heroku.rb deleted file mode 100644 index 963f164ce..000000000 --- a/lib/suspenders/adapters/heroku.rb +++ /dev/null @@ -1,136 +0,0 @@ -module Suspenders - module Adapters - class Heroku - def initialize(app_builder) - @app_builder = app_builder - end - - def set_heroku_remotes - remotes = <<~SHELL - #{command_to_join_heroku_app("staging")} - #{command_to_join_heroku_app("production")} - - git config heroku.remote staging - SHELL - - app_builder.append_file "bin/setup", remotes - end - - def create_staging_heroku_app(flags) - app_name = heroku_app_name_for("staging") - - run_toolbelt_command "create #{app_name} #{flags}", "staging" - end - - def create_production_heroku_app(flags) - app_name = heroku_app_name_for("production") - - run_toolbelt_command "create #{app_name} #{flags}", "production" - end - - def set_heroku_rails_secrets - %w[staging production].each do |environment| - run_toolbelt_command( - "config:add SECRET_KEY_BASE=#{generate_secret}", - environment - ) - end - end - - def set_heroku_honeybadger_env - %w[staging production].each do |environment| - run_toolbelt_command( - "config:add HONEYBADGER_ENV=#{environment}", - environment - ) - end - end - - def set_heroku_backup_schedule - %w[staging production].each do |environment| - run_toolbelt_command( - "pg:backups:schedule DATABASE_URL --at '10:00 UTC'", - environment - ) - end - end - - def create_heroku_pipeline - pipelines_plugin = `heroku help | grep pipelines` - if pipelines_plugin.empty? - puts "You need heroku pipelines plugin. Run: brew upgrade heroku-toolbelt" - exit 1 - end - - run_toolbelt_command( - "pipelines:create #{heroku_app_name} \ - -a #{heroku_app_name}-staging --stage staging", - "staging" - ) - - run_toolbelt_command( - "pipelines:add #{heroku_app_name} \ - -a #{heroku_app_name}-production --stage production", - "production" - ) - end - - def set_heroku_application_host - %w[staging production].each do |environment| - run_toolbelt_command( - "config:add APPLICATION_HOST=#{heroku_app_name}-#{environment}.herokuapp.com", - environment - ) - end - end - - def set_heroku_buildpacks - %w[staging production].each do |environment| - run_toolbelt_command( - "buildpacks:add --index 1 heroku/nodejs", - environment - ) - run_toolbelt_command( - "buildpacks:add --index 2 heroku/ruby", - environment - ) - end - end - - private - - attr_reader :app_builder - - def command_to_join_heroku_app(environment) - heroku_app_name = heroku_app_name_for(environment) - <<~SHELL - - if heroku apps:info --app #{heroku_app_name} > /dev/null 2>&1; then - git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true - printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n' - else - printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n' - fi - SHELL - end - - def heroku_app_name - app_builder.app_name.dasherize - end - - def heroku_app_name_for(environment) - "#{heroku_app_name}-#{environment}" - end - - def generate_secret - SecureRandom.hex(64) - end - - def run_toolbelt_command(command, environment) - app_builder.run( - "heroku #{command} --remote #{environment}" - ) - end - end - end -end diff --git a/lib/suspenders/app_builder.rb b/lib/suspenders/app_builder.rb deleted file mode 100644 index a2f8ab652..000000000 --- a/lib/suspenders/app_builder.rb +++ /dev/null @@ -1,267 +0,0 @@ -require "forwardable" - -module Suspenders - class AppBuilder < Rails::AppBuilder - include Suspenders::Actions - extend Forwardable - - def_delegators( - :heroku_adapter, - :create_heroku_pipeline, - :create_production_heroku_app, - :create_staging_heroku_app, - :set_heroku_application_host, - :set_heroku_backup_schedule, - :set_heroku_honeybadger_env, - :set_heroku_rails_secrets, - :set_heroku_remotes, - :set_heroku_buildpacks - ) - - def readme - template "README.md.erb", "README.md" - end - - def gitignore - copy_file "suspenders_gitignore", ".gitignore" - end - - def gemfile - template "Gemfile.erb", "Gemfile" - end - - def setup_rack_mini_profiler - copy_file( - "rack_mini_profiler.rb", - "config/initializers/rack_mini_profiler.rb" - ) - end - - def raise_on_missing_assets_in_test - configure_environment "test", "config.assets.raise_runtime_errors = true" - end - - def raise_on_delivery_errors - replace_in_file "config/environments/development.rb", - "raise_delivery_errors = false", "raise_delivery_errors = true" - end - - def set_test_delivery_method - inject_into_file( - "config/environments/development.rb", - "\n config.action_mailer.delivery_method = :file", - after: "config.action_mailer.raise_delivery_errors = true" - ) - end - - def raise_on_unpermitted_parameters - config = <<-RUBY - config.action_controller.action_on_unpermitted_parameters = :raise - RUBY - - inject_into_class "config/application.rb", "Application", config - end - - def configure_quiet_assets - config = <<-RUBY - config.assets.quiet = true - RUBY - - inject_into_class "config/application.rb", "Application", config - end - - def provide_setup_script - template "bin_setup", "bin/setup", force: true - run "chmod a+x bin/setup" - end - - def provide_yarn_script - template "bin_yarn", "bin/yarn", force: true - run "chmod a+x bin/yarn" - end - - def configure_generators - config = <<-RUBY - - config.generators do |generate| - generate.helper false - generate.javascripts false - generate.controller_specs false - generate.request_specs true - generate.routing_specs false - generate.stylesheets false - generate.test_framework :rspec - generate.view_specs false - end - - RUBY - - inject_into_class "config/application.rb", "Application", config - end - - def configure_local_mail - copy_file "email.rb", "config/initializers/email.rb" - end - - def setup_asset_host - replace_in_file "config/environments/production.rb", - %(# config.asset_host = "http://assets.example.com"), - 'config.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))' - - if File.exist?("config/initializers/assets.rb") - replace_in_file "config/initializers/assets.rb", - %(Rails.application.config.assets.version = "1.0"), - 'Rails.application.config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")' - end - - config = <<~EOD - config.public_file_server.headers = { - "Cache-Control" => "public, max-age=31557600", - } - EOD - - configure_environment("production", config) - end - - def setup_secret_token - template "secrets.yml", "config/secrets.yml", force: true - end - - def disallow_wrapping_parameters - remove_file "config/initializers/wrap_parameters.rb" - end - - def use_postgres_config_template - template "postgresql_database.yml.erb", "config/database.yml", - force: true - end - - def create_database - bundle_command "exec rails db:create db:migrate" - end - - def run_database_migrations - bundle_command "exec rails db:migrate" - end - - def replace_gemfile - template "Gemfile.erb", "Gemfile", force: true do |content| - if development_env? - content.gsub(%r{gem .suspenders.}) { |s| %(#{s}, path: "#{root_path}") } - else - content - end - end - end - - def ruby_version - create_file ".ruby-version", "#{RUBY_VERSION}\n" - end - - def configure_i18n_for_missing_translations - raise_on_missing_translations_in("development") - raise_on_missing_translations_in("test") - end - - def configure_action_mailer_in_specs - copy_file "action_mailer.rb", "spec/support/action_mailer.rb" - end - - def configure_time_formats - remove_file "config/locales/en.yml" - template "config_locales_en.yml.erb", "config/locales/en.yml" - end - - def configure_action_mailer - action_mailer_host "development", %("localhost:3000") - action_mailer_asset_host "development", %("http://localhost:3000") - action_mailer_host "test", %("www.example.com") - action_mailer_asset_host "test", %("http://www.example.com") - action_mailer_host "production", %{ENV.fetch("APPLICATION_HOST")} - # rubocop:disable Lint/InterpolationCheck - action_mailer_asset_host( - "production", - %q{"https://#{ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))}"} - ) - # rubocop:enable Lint/InterpolationCheck - end - - def create_heroku_apps(flags) - create_staging_heroku_app(flags) - create_production_heroku_app(flags) - end - - def configure_automatic_deployment - append_file "Procfile", "release: bin/auto_migrate\n" - copy_file "bin_auto_migrate", "bin/auto_migrate" - end - - def create_github_repo(repo_name) - run "hub create #{repo_name}" - end - - def copy_miscellaneous_files - copy_file "errors.rb", "config/initializers/errors.rb" - copy_file "json_encoding.rb", "config/initializers/json_encoding.rb" - end - - def remove_config_comment_lines - config_files = [ - "application.rb", - "environment.rb", - "environments/development.rb", - "environments/production.rb", - "environments/test.rb" - ] - - config_files.each do |config_file| - path = Pathname(destination_root).join("config", config_file) - source = Actions::StripCommentsAction.call(path.read) - - path.write(source) - end - end - - def remove_routes_comment_lines - replace_in_file "config/routes.rb", - /Rails\.application\.routes\.draw do.*end/m, - "Rails.application.routes.draw do\nend" - end - - def setup_default_rake_task - append_file "Rakefile" do - <<~EOS - task(:default).clear - task default: [:spec] - - if defined? RSpec - task(:spec).clear - RSpec::Core::RakeTask.new(:spec) do |t| - t.verbose = false - end - end - EOS - end - end - - private - - def root_path - @root_path ||= Pathname(__dir__).join("..", "..").expand_path - end - - def development_env? - root_path.join("suspenders.gemspec").exist? - end - - def raise_on_missing_translations_in(environment) - config = "config.i18n.raise_on_missing_translations = true" - - uncomment_lines("config/environments/#{environment}.rb", config) - end - - def heroku_adapter - @heroku_adapter ||= Adapters::Heroku.new(self) - end - end -end diff --git a/lib/suspenders/exit_on_failure.rb b/lib/suspenders/exit_on_failure.rb deleted file mode 100644 index 5c2766f84..000000000 --- a/lib/suspenders/exit_on_failure.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "active_support/concern" -require "English" - -module Suspenders - module ExitOnFailure - extend ActiveSupport::Concern - - def bundle_command(*) - super - exit(false) if $CHILD_STATUS.exitstatus.nonzero? - end - - module ClassMethods - def exit_on_failure? - true - end - end - end -end diff --git a/lib/suspenders/generators/accessibility_generator.rb b/lib/suspenders/generators/accessibility_generator.rb deleted file mode 100644 index 89cf5f147..000000000 --- a/lib/suspenders/generators/accessibility_generator.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative "base" - -module Suspenders - class AccessibilityGenerator < Generators::Base - def capybara_gems - gem "capybara_accessibility_audit", group: [:test] - gem "capybara_accessible_selectors", group: [:test], - github: "citizensadvice/capybara_accessible_selectors" - Bundler.with_unbundled_env { run "bundle install" } - end - end -end diff --git a/lib/suspenders/generators/advisories_generator.rb b/lib/suspenders/generators/advisories_generator.rb deleted file mode 100644 index 72d442415..000000000 --- a/lib/suspenders/generators/advisories_generator.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative "base" - -module Suspenders - class AdvisoriesGenerator < Generators::Base - def bundler_audit_gem - gem "bundler-audit", ">= 0.7.0", require: false, group: [:development, :test] - Bundler.with_unbundled_env { run "bundle install" } - end - - def rake_task - copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake" - append_file "Rakefile", %(\ntask default: "bundle:audit"\n) - end - end -end diff --git a/lib/suspenders/generators/analytics_generator.rb b/lib/suspenders/generators/analytics_generator.rb deleted file mode 100644 index 12b33e228..000000000 --- a/lib/suspenders/generators/analytics_generator.rb +++ /dev/null @@ -1,24 +0,0 @@ -require_relative "base" - -module Suspenders - class AnalyticsGenerator < Generators::Base - def install_partial - copy_file "_analytics.html.erb", - "app/views/application/_analytics.html.erb" - end - - def render_partial - if File.exist?(js_partial) - inject_into_file js_partial, - %(\n\n<%= render "analytics" %>), - after: "<%= yield :javascript %>" - end - end - - private - - def js_partial - "app/views/application/_javascript.html.erb" - end - end -end diff --git a/lib/suspenders/generators/app_generator.rb b/lib/suspenders/generators/app_generator.rb deleted file mode 100644 index 94ea28c1d..000000000 --- a/lib/suspenders/generators/app_generator.rb +++ /dev/null @@ -1,215 +0,0 @@ -require "rails/generators" -require "rails/generators/rails/app/app_generator" - -module Suspenders - class AppGenerator < Rails::Generators::AppGenerator - include ExitOnFailure - - hide! - - class_option :database, type: :string, aliases: "-d", default: "postgresql", - desc: "Configure for selected database (options: #{DATABASES.join("/")})" - - class_option :heroku, type: :boolean, aliases: "-H", default: false, - desc: "Create staging and production Heroku apps" - - class_option :heroku_flags, type: :string, default: "", - desc: "Set extra Heroku flags" - - class_option :github, type: :string, default: nil, - desc: "Create Github repository and add remote origin pointed to repo" - - class_option :version, type: :boolean, aliases: "-v", group: :suspenders, - desc: "Show Suspenders version number and quit" - - class_option :help, type: :boolean, aliases: "-h", group: :suspenders, - desc: "Show this help message and quit" - - class_option :skip_test, type: :boolean, default: true, - desc: "Skip Test Unit" - - class_option :skip_system_test, - type: :boolean, default: true, desc: "Skip system test files" - - class_option :css, - type: :string, default: "postcss", aliases: "-c", desc: "Choose CSS processor" - - def finish_template - invoke :suspenders_customization - super - end - - def leftovers - generate("suspenders:stylesheet_base") unless options[:api] || options[:css] != "postcss" - invoke :outro - end - - def suspenders_customization - invoke :customize_gemfile - invoke :setup_development_environment - invoke :setup_production_environment - invoke :setup_secret_token - invoke :configure_app - invoke :copy_miscellaneous_files - invoke :setup_database - invoke :create_github_repo - invoke :generate_default - invoke :create_heroku_apps - invoke :generate_deployment_default - invoke :remove_config_comment_lines - invoke :remove_routes_comment_lines - invoke :run_database_migrations - invoke :generate_views - end - - def customize_gemfile - build :replace_gemfile - bundle_command "install" - end - - def setup_database - say "Setting up database" - - if options[:database] == "postgresql" - build :use_postgres_config_template - end - - build :create_database - end - - def setup_development_environment - say "Setting up the development environment" - build :configure_local_mail - build :raise_on_missing_assets_in_test - build :raise_on_delivery_errors - build :set_test_delivery_method - build :raise_on_unpermitted_parameters - build :provide_setup_script - build :provide_yarn_script - build :configure_generators - build :configure_i18n_for_missing_translations - build :configure_quiet_assets - end - - def setup_production_environment - say "Setting up the production environment" - build :setup_asset_host - end - - def setup_secret_token - say "Moving secret token out of version control" - build :setup_secret_token - end - - def configure_app - say "Configuring app" - build :configure_action_mailer - build :configure_time_formats - build :setup_default_rake_task - end - - def create_heroku_apps - if options[:heroku] - say "Creating Heroku apps" - build :create_heroku_apps, options[:heroku_flags] - build :set_heroku_remotes - build :set_heroku_rails_secrets - build :set_heroku_application_host - build :set_heroku_honeybadger_env - build :set_heroku_backup_schedule - build :set_heroku_buildpacks - build :create_heroku_pipeline - build :configure_automatic_deployment - end - end - - def create_github_repo - if !options[:skip_git] && options[:github] - say "Creating Github repo" - build :create_github_repo, options[:github] - end - end - - def copy_miscellaneous_files - say "Copying miscellaneous support files" - build :copy_miscellaneous_files - end - - def remove_config_comment_lines - build :remove_config_comment_lines - end - - def remove_routes_comment_lines - build :remove_routes_comment_lines - end - - def run_database_migrations - build :run_database_migrations - end - - def generate_default - run("spring stop > /dev/null 2>&1 || true") - generate("suspenders:runner") - generate("suspenders:profiler") - generate("suspenders:json") - generate("suspenders:static") - generate("suspenders:testing") - generate("suspenders:ci") - generate("suspenders:js_driver") - generate("suspenders:forms") unless options[:api] - generate("suspenders:db_optimizations") - generate("suspenders:factories") - generate("suspenders:lint") - generate("suspenders:jobs") - generate("suspenders:analytics") - generate("suspenders:inline_svg") - generate("suspenders:advisories") - end - - def generate_deployment_default - generate("suspenders:staging:pull_requests") - generate("suspenders:production:single_redirect") - generate("suspenders:production:compression") - generate("suspenders:production:force_tls") - generate("suspenders:production:email") - generate("suspenders:production:timeout") - generate("suspenders:production:deployment") - generate("suspenders:production:manifest") - end - - def generate_views - generate("suspenders:views") - end - - def outro - say "\nCongratulations! You just pulled our suspenders." - say honeybadger_outro - end - - def self.banner - "suspenders #{arguments.map(&:usage).join(" ")} [options]" - end - - protected - - def get_builder_class - Suspenders::AppBuilder - end - - def using_active_record? - !options[:skip_active_record] - end - - private - - def honeybadger_outro - "Run 'bundle exec honeybadger heroku install' with your API key#{honeybadger_message_suffix}." - end - - def honeybadger_message_suffix - if options[:heroku] - " unless you're using the Heroku Honeybadger add-on" - end - end - end -end diff --git a/lib/suspenders/generators/base.rb b/lib/suspenders/generators/base.rb deleted file mode 100644 index b48b2d6f5..000000000 --- a/lib/suspenders/generators/base.rb +++ /dev/null @@ -1,60 +0,0 @@ -require "rails/generators" -require_relative "../actions" - -module Suspenders - module Generators - class Base < Rails::Generators::Base - include Suspenders::Actions - include ExitOnFailure - - def self.default_source_root - File.expand_path(File.join("..", "..", "..", "templates"), __dir__) - end - - def self.inherited(subclass) - super - - description_file = File.expand_path( - File.join( - default_source_root, - "descriptions", - "#{subclass.generator_name}.md" - ) - ) - - subclass.desc File.read(description_file) - rescue Errno::ENOENT - end - - private - - def app_name - Rails.app_class.module_parent_name.demodulize.underscore.dasherize - end - - def empty_directory_with_keep_file(destination) - empty_directory(destination, {}) - keep_file(destination) - end - - def keep_file(destination) - create_file(File.join(destination, ".keep")) - end - - def append_template_to_file(destination, source, *args) - partial = File.expand_path(find_in_source_paths(source)) - append_to_file(destination, File.read(partial, *args)) - end - - def prepend_template_to_file(destination, source, *args) - partial = File.expand_path(find_in_source_paths(source)) - prepend_to_file(destination, File.read(partial, *args)) - end - - def inject_template_into_file(destination, source, *args) - partial = File.expand_path(find_in_source_paths(source)) - inject_into_file(destination, File.read(partial), *args) - end - end - end -end diff --git a/lib/suspenders/generators/ci_generator.rb b/lib/suspenders/generators/ci_generator.rb deleted file mode 100644 index ab08c59a3..000000000 --- a/lib/suspenders/generators/ci_generator.rb +++ /dev/null @@ -1,32 +0,0 @@ -require_relative "base" - -module Suspenders - class CiGenerator < Generators::Base - def simplecov_gem - gem "simplecov", require: false, group: [:test] - Bundler.with_unbundled_env { run "bundle install" } - end - - def simplecov_test_integration - prepend_template_to_file(test_helper_file, "partials/ci_simplecov.rb") - end - - def configure_ci - template "circle.yml.erb", "circle.yml" - end - - private - - def test_helper_file - if using_rspec? - "spec/spec_helper.rb" - else - "test/test_helper.rb" - end - end - - def using_rspec? - File.exist?("spec/spec_helper.rb") - end - end -end diff --git a/lib/suspenders/generators/db_optimizations_generator.rb b/lib/suspenders/generators/db_optimizations_generator.rb deleted file mode 100644 index fc32c339e..000000000 --- a/lib/suspenders/generators/db_optimizations_generator.rb +++ /dev/null @@ -1,18 +0,0 @@ -require_relative "base" - -module Suspenders - class DbOptimizationsGenerator < Generators::Base - def add_bullet - gem "bullet", group: %i[development test] - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_bullet - inject_template_into_file( - "config/environments/development.rb", - "partials/db_optimizations_configuration.rb", - after: /config.action_mailer.raise_delivery_errors = .*/ - ) - end - end -end diff --git a/lib/suspenders/generators/factories_generator.rb b/lib/suspenders/generators/factories_generator.rb deleted file mode 100644 index 70392322c..000000000 --- a/lib/suspenders/generators/factories_generator.rb +++ /dev/null @@ -1,22 +0,0 @@ -require_relative "base" - -module Suspenders - class FactoriesGenerator < Generators::Base - def add_factory_bot - gem "factory_bot_rails", group: %i[development test] - Bundler.with_unbundled_env { run "bundle install" } - end - - def set_up_factory_bot_for_rspec - copy_file "factory_bot_rspec.rb", "spec/support/factory_bot.rb" - end - - def generate_empty_factories_file - copy_file "factories.rb", "spec/factories.rb" - end - - def provide_dev_prime_task - copy_file "dev.rake", "lib/tasks/dev.rake" - end - end -end diff --git a/lib/suspenders/generators/forms_generator.rb b/lib/suspenders/generators/forms_generator.rb deleted file mode 100644 index 6ea2aca80..000000000 --- a/lib/suspenders/generators/forms_generator.rb +++ /dev/null @@ -1,18 +0,0 @@ -require_relative "base" - -module Suspenders - class FormsGenerator < Generators::Base - def add_simple_form - gem "simple_form" - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_simple_form - create_file "config/initializers/simple_form.rb" do - "SimpleForm.setup {|config|}" - end - - generate "simple_form:install", "--force" - end - end -end diff --git a/lib/suspenders/generators/inline_svg_generator.rb b/lib/suspenders/generators/inline_svg_generator.rb deleted file mode 100644 index 1ff39c16c..000000000 --- a/lib/suspenders/generators/inline_svg_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "base" - -module Suspenders - class InlineSvgGenerator < Generators::Base - def add_inline_svg - gem "inline_svg" - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_inline_svg - copy_file "inline_svg.rb", "config/initializers/inline_svg.rb" - end - end -end diff --git a/lib/suspenders/generators/jobs_generator.rb b/lib/suspenders/generators/jobs_generator.rb deleted file mode 100644 index 23d512959..000000000 --- a/lib/suspenders/generators/jobs_generator.rb +++ /dev/null @@ -1,37 +0,0 @@ -require_relative "base" - -module Suspenders - class JobsGenerator < Generators::Base - def add_jobs_gem - gem "sidekiq" - Bundler.with_unbundled_env { run "bundle install" } - end - - def initialize_active_job - copy_file( - "active_job.rb", - "config/initializers/active_job.rb" - ) - end - - def configure_active_job - configure_application_file("config.active_job.queue_adapter = :sidekiq") - configure_application_file("config.action_mailer.deliver_later_queue_name = nil") - configure_application_file("config.action_mailbox.queues.routing = nil") - configure_application_file("config.active_storage.queues.analysis = nil") - configure_application_file("config.active_storage.queues.purge = nil") - configure_application_file("config.active_storage.queues.mirror = nil") - configure_environment "test", "config.active_job.queue_adapter = :inline" - end - - private - - def configure_application_file(config) - inject_into_file( - "config/application.rb", - "\n #{config}", - before: "\n end" - ) - end - end -end diff --git a/lib/suspenders/generators/js_driver_generator.rb b/lib/suspenders/generators/js_driver_generator.rb deleted file mode 100644 index fe4e1ba6e..000000000 --- a/lib/suspenders/generators/js_driver_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "base" - -module Suspenders - class JsDriverGenerator < Generators::Base - def add_gems - gem "webdrivers", group: :test - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_capybara - copy_file "chromedriver.rb", "spec/support/chromedriver.rb" - end - end -end diff --git a/lib/suspenders/generators/json_generator.rb b/lib/suspenders/generators/json_generator.rb deleted file mode 100644 index 7d7245af4..000000000 --- a/lib/suspenders/generators/json_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "base" - -module Suspenders - class JsonGenerator < Generators::Base - def add_oj - gem "oj" - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_oj - copy_file "oj.rb", "config/initializers/oj.rb" - end - end -end diff --git a/lib/suspenders/generators/lint_generator.rb b/lib/suspenders/generators/lint_generator.rb deleted file mode 100644 index 4b897f5d5..000000000 --- a/lib/suspenders/generators/lint_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "base" - -module Suspenders - class LintGenerator < Generators::Base - def set_up_hound - copy_file "hound.yml", ".hound.yml" - end - - def set_up_standard - gem "standard", group: :development - prepend_to_file("Rakefile", 'require "standard/rake"') - end - end -end diff --git a/lib/suspenders/generators/production/compression_generator.rb b/lib/suspenders/generators/production/compression_generator.rb deleted file mode 100644 index 4f6f7ccb7..000000000 --- a/lib/suspenders/generators/production/compression_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class CompressionGenerator < Generators::Base - def add_rack_deflater - configure_environment( - :production, - %(config.middleware.use Rack::Deflater) - ) - end - end - end -end diff --git a/lib/suspenders/generators/production/deployment_generator.rb b/lib/suspenders/generators/production/deployment_generator.rb deleted file mode 100644 index 50ee73be4..000000000 --- a/lib/suspenders/generators/production/deployment_generator.rb +++ /dev/null @@ -1,16 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class DeploymentGenerator < Generators::Base - def copy_script - copy_file "bin_deploy", "bin/deploy" - chmod "bin/deploy", 0o755 - end - - def inform_user - append_template_to_file "README.md", "partials/deployment_readme.md" - end - end - end -end diff --git a/lib/suspenders/generators/production/email_generator.rb b/lib/suspenders/generators/production/email_generator.rb deleted file mode 100644 index 194eb9373..000000000 --- a/lib/suspenders/generators/production/email_generator.rb +++ /dev/null @@ -1,34 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class EmailGenerator < Generators::Base - def smtp_configuration - copy_file "smtp.rb", "config/smtp.rb" - - prepend_file "config/environments/production.rb", - %{require Rails.root.join("config/smtp")\n\n} - end - - def use_smtp - inject_template_into_file( - "config/environments/production.rb", - "partials/email_smtp.rb", - after: "config.action_mailer.perform_caching = false\n" - ) - end - - def env_vars - expand_json( - "app.json", - env: { - SMTP_ADDRESS: {required: true}, - SMTP_DOMAIN: {required: true}, - SMTP_PASSWORD: {required: true}, - SMTP_USERNAME: {required: true} - } - ) - end - end - end -end diff --git a/lib/suspenders/generators/production/force_tls_generator.rb b/lib/suspenders/generators/production/force_tls_generator.rb deleted file mode 100644 index 51f246a92..000000000 --- a/lib/suspenders/generators/production/force_tls_generator.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class ForceTlsGenerator < Generators::Base - def config_enforce_ssl - configure_environment "production", "config.force_ssl = true" - end - end - end -end diff --git a/lib/suspenders/generators/production/manifest_generator.rb b/lib/suspenders/generators/production/manifest_generator.rb deleted file mode 100644 index 77547d1e0..000000000 --- a/lib/suspenders/generators/production/manifest_generator.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class ManifestGenerator < Generators::Base - def render_manifest - expand_json( - "app.json", - name: app_name.dasherize, - scripts: {}, - env: { - APPLICATION_HOST: {required: true}, - AUTO_MIGRATE_DB: {value: true}, - EMAIL_RECIPIENTS: {required: true}, - HEROKU_APP_NAME: {required: true}, - HEROKU_PARENT_APP_NAME: {required: true}, - RACK_ENV: {required: true}, - SECRET_KEY_BASE: {generator: "secret"} - }, - addons: ["heroku-postgresql", "heroku-redis"] - ) - end - end - end -end diff --git a/lib/suspenders/generators/production/single_redirect.rb b/lib/suspenders/generators/production/single_redirect.rb deleted file mode 100644 index 91e77d0b1..000000000 --- a/lib/suspenders/generators/production/single_redirect.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class SingleRedirect < Generators::Base - def add_rack_canonical_host - inject_into_file( - "config/environments/production.rb", - %{\n config.middleware.use Rack::CanonicalHost, ENV.fetch("APPLICATION_HOST")}, - before: "\nend" - ) - end - end - end -end diff --git a/lib/suspenders/generators/production/timeout_generator.rb b/lib/suspenders/generators/production/timeout_generator.rb deleted file mode 100644 index c5cfd1354..000000000 --- a/lib/suspenders/generators/production/timeout_generator.rb +++ /dev/null @@ -1,22 +0,0 @@ -require_relative "../base" - -module Suspenders - module Production - class TimeoutGenerator < Generators::Base - def add_gem - gem "rack-timeout", group: :production - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_rack_timeout - append_file ".sample.env", rack_timeout_config - end - - private - - def rack_timeout_config - %(RACK_TIMEOUT_SERVICE_TIMEOUT=10) - end - end - end -end diff --git a/lib/suspenders/generators/profiler_generator.rb b/lib/suspenders/generators/profiler_generator.rb deleted file mode 100644 index c0ed0d46c..000000000 --- a/lib/suspenders/generators/profiler_generator.rb +++ /dev/null @@ -1,35 +0,0 @@ -require_relative "base" - -module Suspenders - class ProfilerGenerator < Generators::Base - def augment_default_env - append_to_file ".sample.env", "RACK_MINI_PROFILER=0\n" - rescue Errno::ENOENT - create_file ".sample.env", "RACK_MINI_PROFILER=0\n" - rescue Thor::Error => e - if e.message.match?(/does not appear to exist/) - create_file ".sample.env", "RACK_MINI_PROFILER=0\n" - else - raise - end - end - - def add_gem - gem "rack-mini-profiler", require: false - Bundler.with_unbundled_env { run "bundle install" } - end - - def configure_rack_mini_profiler - copy_file( - "rack_mini_profiler.rb", - "config/initializers/rack_mini_profiler.rb", - force: false, - skip: true - ) - end - - def update_readme - append_template_to_file "README.md", "partials/profiler_readme.md" - end - end -end diff --git a/lib/suspenders/generators/runner_generator.rb b/lib/suspenders/generators/runner_generator.rb deleted file mode 100644 index 266c3ce05..000000000 --- a/lib/suspenders/generators/runner_generator.rb +++ /dev/null @@ -1,48 +0,0 @@ -require_relative "base" - -module Suspenders - class RunnerGenerator < Generators::Base - def procfile - copy_file "Procfile", "Procfile" - end - - def sample_env - copy_file "sample_env", ".sample.env" - end - - def copy_sample_env - if bin_setup_is_ruby? - inject_template_into_file( - "bin/setup", - "partials/runner_setup.rb", - before: %( puts "\\n== Preparing database ==") - ) - elsif bin_setup_mentions_ci? - inject_into_file( - "bin/setup", - %( cp -i .sample.env .env\n), - after: %(if [ -z "$CI" ]; then\n) - ) - else - append_to_file( - "bin/setup", - %(\nif [ -z "$CI" ]; then\n cp -i .sample.env .env\nfi) - ) - end - end - - def update_readme - append_template_to_file "README.md", "partials/runner_readme.md" - end - - private - - def bin_setup_is_ruby? - File.read("bin/setup", 20).match?(%r{#!/usr/bin/env ruby}) - end - - def bin_setup_mentions_ci? - File.read("bin/setup").match?(/if \[ -z "\$CI" \]/) - end - end -end diff --git a/lib/suspenders/generators/staging/pull_requests_generator.rb b/lib/suspenders/generators/staging/pull_requests_generator.rb deleted file mode 100644 index ebed65849..000000000 --- a/lib/suspenders/generators/staging/pull_requests_generator.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_relative "../base" - -module Suspenders - module Staging - class PullRequestsGenerator < Generators::Base - def configure_heroku_staging_pr_pipeline_host - inject_template_into_file( - "config/environments/production.rb", - "partials/pull_requests_config.rb", - after: "Rails.application.configure do\n" - ) - end - - def create_review_apps_setup_script - template( - "bin_setup_review_app.erb", - "bin/setup_review_app", - force: true - ) - - run "chmod a+x bin/setup_review_app" - end - end - end -end diff --git a/lib/suspenders/generators/static_generator.rb b/lib/suspenders/generators/static_generator.rb deleted file mode 100644 index 215ee325d..000000000 --- a/lib/suspenders/generators/static_generator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative "base" - -module Suspenders - class StaticGenerator < Generators::Base - def add_high_voltage - gem "high_voltage" - Bundler.with_unbundled_env { run "bundle install" } - end - - def make_placeholder_directory - empty_directory_with_keep_file "app/views/pages" - end - end -end diff --git a/lib/suspenders/generators/stylelint_generator.rb b/lib/suspenders/generators/stylelint_generator.rb deleted file mode 100644 index 5f574da7a..000000000 --- a/lib/suspenders/generators/stylelint_generator.rb +++ /dev/null @@ -1,71 +0,0 @@ -require_relative "base" - -module Suspenders - class StylelintGenerator < Generators::Base - def setup_hound - action InvokeGenerator.new(self, "suspenders:lint") - action ToggleComments.new(self, ".hound.yml", /stylelintrc/) - end - - def install_stylelint - dependencies = ["stylelint", "@thoughtbot/stylelint-config"] - action YarnInstall.new(self, dependencies, "--dev") - end - - def copy_stylelint_config - copy_file "stylelintrc.json", ".stylelintrc.json" - end - - class InvokeGenerator - def initialize(base, generator) - @base = base - @generator = generator - end - - def invoke! - @base.invoke @generator - end - - def revoke! - end - end - - class ToggleComments - def initialize(base, filename, pattern) - @base = base - @filename = filename - @pattern = pattern - end - - def invoke! - @base.uncomment_lines(@filename, @pattern) - end - - def revoke! - @base.behavior = :invoke - @base.comment_lines(@filename, @pattern) - ensure - @base.behavior = :revoke - end - end - - class YarnInstall - def initialize(base, dependencies, flags) - @base = base - @dependencies = dependencies.join(" ") - @flags = flags - end - - def invoke! - @base.run "bin/yarn add #{@dependencies} #{@flags}" - end - - def revoke! - @base.behavior = :invoke - @base.run "bin/yarn remove #{@dependencies}" - ensure - @base.behavior = :revoke - end - end - end -end diff --git a/lib/suspenders/generators/stylesheet_base_generator.rb b/lib/suspenders/generators/stylesheet_base_generator.rb deleted file mode 100644 index 15c12b058..000000000 --- a/lib/suspenders/generators/stylesheet_base_generator.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative "base" - -module Suspenders - class StylesheetBaseGenerator < Generators::Base - def setup_normalize - run "yarn add postcss-normalize" - copy_file( - "application.postcss.css", - "app/assets/stylesheets/application.postcss.css", - force: true - ) - copy_file "postcss.config.js", "postcss.config.js", force: true - end - end -end diff --git a/lib/suspenders/generators/testing_generator.rb b/lib/suspenders/generators/testing_generator.rb deleted file mode 100644 index f2a1a6715..000000000 --- a/lib/suspenders/generators/testing_generator.rb +++ /dev/null @@ -1,43 +0,0 @@ -require_relative "base" - -module Suspenders - class TestingGenerator < Generators::Base - def add_testing_gems - gem "rspec-rails", "~> 5.1", group: %i[development test] - gem "shoulda-matchers", group: :test - - Bundler.with_unbundled_env { run "bundle install" } - end - - def generate_rspec - generate "rspec:install" - end - - def configure_rspec - remove_file "spec/rails_helper.rb" - remove_file "spec/spec_helper.rb" - copy_file "rails_helper.rb", "spec/rails_helper.rb" - copy_file "spec_helper.rb", "spec/spec_helper.rb" - end - - def provide_shoulda_matchers_config - copy_file( - "shoulda_matchers_config_rspec.rb", - "spec/support/shoulda_matchers.rb" - ) - end - - def configure_system_tests - empty_directory_with_keep_file "spec/system" - empty_directory_with_keep_file "spec/support/system" - end - - def configure_i18n_for_test_environment - copy_file "i18n.rb", "spec/support/i18n.rb" - end - - def configure_action_mailer_in_specs - copy_file "action_mailer.rb", "spec/support/action_mailer.rb" - end - end -end diff --git a/lib/suspenders/generators/views_generator.rb b/lib/suspenders/generators/views_generator.rb deleted file mode 100644 index 68d94f65b..000000000 --- a/lib/suspenders/generators/views_generator.rb +++ /dev/null @@ -1,25 +0,0 @@ -require_relative "base" - -module Suspenders - class ViewsGenerator < Generators::Base - def create_partials_directory - empty_directory "app/views/application" - end - - def create_shared_flashes - copy_file "_flashes.html.erb", "app/views/application/_flashes.html.erb" - copy_file "flashes_helper.rb", "app/helpers/flashes_helper.rb" - end - - def create_shared_css_overrides - copy_file "_css_overrides.html.erb", - "app/views/application/_css_overrides.html.erb" - end - - def create_application_layout - template "suspenders_layout.html.erb.erb", - "app/views/layouts/application.html.erb", - force: true - end - end -end diff --git a/lib/suspenders/railtie.rb b/lib/suspenders/railtie.rb new file mode 100644 index 000000000..7f02195b1 --- /dev/null +++ b/lib/suspenders/railtie.rb @@ -0,0 +1,4 @@ +module Suspenders + class Railtie < ::Rails::Railtie + end +end diff --git a/lib/suspenders/version.rb b/lib/suspenders/version.rb index 4cf6b0e20..8f46d901c 100644 --- a/lib/suspenders/version.rb +++ b/lib/suspenders/version.rb @@ -1,9 +1,5 @@ module Suspenders - RAILS_VERSION = "~> 7.0.0".freeze - - minimum_ruby_version = "3.0.5" - maximum_ruby_version = Pathname(__dir__).join("../../.ruby-version").read.strip - - RUBY_VERSION_RANGE = [minimum_ruby_version, maximum_ruby_version].freeze - VERSION = "20230113.0".freeze + VERSION = "3.0.0".freeze + RAILS_VERSION = "~> 7.0".freeze + MINIMUM_RUBY_VERSION = ">= 3.1".freeze end diff --git a/lib/tasks/suspenders_tasks.rake b/lib/tasks/suspenders_tasks.rake new file mode 100644 index 000000000..bad21522c --- /dev/null +++ b/lib/tasks/suspenders_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :suspenders do +# # Task goes here +# end diff --git a/spec/adapters/heroku_spec.rb b/spec/adapters/heroku_spec.rb deleted file mode 100644 index a574bc646..000000000 --- a/spec/adapters/heroku_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -require "spec_helper" - -module Suspenders - module Adapters - RSpec.describe Heroku do - it "sets the heroku remotes" do - setup_file = "bin/setup" - app_builder = double(app_name: app_name) - allow(app_builder).to receive(:append_file) - - Heroku.new(app_builder).set_heroku_remotes - - expect(app_builder).to have_received(:append_file) - .with(setup_file, /heroku apps:info --app #{app_name.dasherize}-production/) - expect(app_builder).to have_received(:append_file) - .with(setup_file, /heroku apps:info --app #{app_name.dasherize}-staging/) - end - - it "sets the heroku rails secrets" do - app_builder = double(app_name: app_name) - allow(app_builder).to receive(:run) - - Heroku.new(app_builder).set_heroku_rails_secrets - - expect(app_builder).to( - have_configured_var("staging", "SECRET_KEY_BASE") - ) - expect(app_builder).to( - have_configured_var("production", "SECRET_KEY_BASE") - ) - end - - it "sets the heroku backup schedule" do - app_builder = double(app_name: app_name) - allow(app_builder).to receive(:run) - - Heroku.new(app_builder).set_heroku_backup_schedule - - expect(app_builder).to have_backup_schedule("staging") - expect(app_builder).to have_backup_schedule("production") - end - - it "sets the application host" do - app_builder = double(app_name: app_name) - allow(app_builder).to receive(:run) - - Heroku.new(app_builder).set_heroku_application_host - - expect(app_builder).to( - have_configured_var("staging", "APPLICATION_HOST") - ) - - expect(app_builder).to( - have_configured_var("production", "APPLICATION_HOST") - ) - end - - it "configures nodejs and ruby packs" do - app_builder = double(app_name: app_name) - allow(app_builder).to receive(:run) - - Heroku.new(app_builder).set_heroku_buildpacks - - %w[staging production].each do |remote| - expect(app_builder).to( - have_configured_buildpack( - remote_name: remote, index: 1, packname: "heroku/nodejs" - ) - ) - expect(app_builder).to( - have_configured_buildpack( - remote_name: remote, index: 2, packname: "heroku/ruby" - ) - ) - end - end - - def app_name - TestPaths::APP_NAME - end - - def have_backup_schedule(remote_name) - have_received(:run) - .with(/pg:backups:schedule DATABASE_URL --at '10:00 UTC' --remote #{remote_name}/) - end - - def have_configured_var(remote_name, var) - have_received(:run).with(/config:add #{var}=.+ --remote #{remote_name}/) - end - - def have_configured_buildpack(remote_name:, index:, packname:) - have_received(:run).with( - /buildpacks:add --index #{index} #{packname} --remote #{remote_name}/ - ) - end - end - end -end diff --git a/spec/expand_json_spec.rb b/spec/expand_json_spec.rb deleted file mode 100644 index 36d424a64..000000000 --- a/spec/expand_json_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Actions::ExpandJson do - let(:destination_root) { TestPaths.root_path.join("tmp") } - let(:destination_file_name) { "app.json" } - let(:destination_path) { File.join(destination_root, destination_file_name) } - - before do - FileUtils.rm destination_path if File.exist?(destination_path) - end - - describe "#invoke!" do - context "when calling multiple times with the same root key" do - before do - described_class.new( - destination_root, - destination_file_name, - env: { - SMTP_ADDRESS: {required: true} - } - ).invoke! - end - - it "deep merges the hash" do - described_class.new( - destination_root, - destination_file_name, - env: { - HEROKU_APP_NAME: {required: true} - } - ).invoke! - - expected = <<~JSON - { - "env": { - "SMTP_ADDRESS": { - "required": true - }, - "HEROKU_APP_NAME": { - "required": true - } - } - } - JSON - expect(existing_json).to eq(expected.chomp) - end - end - end - - describe "#revoke!" do - before do - described_class.new( - destination_root, - destination_file_name, - env: { - foo: {required: true}, - bar: {required: true} - } - ).invoke! - end - - it "removes data from the JSON" do - described_class.new( - destination_root, - destination_file_name, - env: { - foo: {required: true} - } - ).revoke! - - expected = <<~JSON - { - "env": { - "bar": { - "required": true - } - } - } - JSON - expect(existing_json).to eq(expected.chomp) - end - end - - private - - def existing_json - IO.read(destination_path) - end -end diff --git a/spec/features/api_spec.rb b/spec/features/api_spec.rb deleted file mode 100644 index 6d8918988..000000000 --- a/spec/features/api_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "spec_helper" - -RSpec.describe "Suspend a new project with --api flag", type: :feature do - before(:all) do - drop_dummy_database - clear_tmp_directory - end - - it "ensures project specs pass" do - run_suspenders!("--api") - - Dir.chdir(project_path) do - Bundler.with_unbundled_env do - expect(`rake`).to include("0 failures") - end - end - end -end diff --git a/spec/features/cli_help_spec.rb b/spec/features/cli_help_spec.rb deleted file mode 100644 index 3f4e00c84..000000000 --- a/spec/features/cli_help_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require "spec_helper" - -RSpec.describe "Command line help output", type: :feature do - let(:help_text) { suspenders_help_command } - - it "does not contain the default rails usage statement" do - expect(help_text).not_to include("rails new APP_PATH [options]") - end - - it "provides the correct usage statement for suspenders" do - expect(help_text).to include <<~EOH - Usage: - suspenders APP_PATH [options] - EOH - end - - it "does not contain the default rails group" do - expect(help_text).not_to include("Rails options:") - end - - it "provides help and version usage within the suspenders group" do - expect(help_text).to include <<~EOH - Suspenders options: - -h, [--help], [--no-help] # Show this help message and quit - -v, [--version], [--no-version] # Show Suspenders version number and quit - EOH - end - - it "does not show the default extended rails help section" do - expect(help_text).not_to include("Create suspenders files for app generator.") - end - - it "contains the usage statement from the suspenders gem" do - expect(help_text).to include IO.read(usage_file) - end -end diff --git a/spec/features/github_spec.rb b/spec/features/github_spec.rb deleted file mode 100644 index cd67c09fc..000000000 --- a/spec/features/github_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "spec_helper" - -RSpec.describe "GitHub", type: :feature do - before do - drop_dummy_database - clear_tmp_directory - end - - it "suspends a project with --github option" do - repo_name = "test" - run_suspenders("--github=#{repo_name}") - setup_app_dependencies - - expect(FakeGithub).to have_created_repo(repo_name) - end -end diff --git a/spec/features/heroku_spec.rb b/spec/features/heroku_spec.rb deleted file mode 100644 index 7d751bff5..000000000 --- a/spec/features/heroku_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require "spec_helper" - -RSpec.describe "Heroku", type: :feature do - context "--heroku" do - before(:all) do - clean_up - run_suspenders("--heroku=true") - setup_app_dependencies - end - - it "suspends a project for Heroku" do - app_name = TestPaths::APP_NAME.dasherize - - expect(FakeHeroku).to have_created_app_for("staging") - expect(FakeHeroku).to have_created_app_for("production") - expect(FakeHeroku).to have_configured_vars("staging", "SECRET_KEY_BASE") - expect(FakeHeroku).to have_configured_vars( - "production", - "SECRET_KEY_BASE" - ) - %w[staging production].each do |env| - expect(FakeHeroku).to have_configured_vars(env, "APPLICATION_HOST") - expect(FakeHeroku).to have_configured_vars(env, "HONEYBADGER_ENV") - end - expect(FakeHeroku).to have_setup_pipeline_for(app_name) - - bin_setup_path = "#{project_path}/bin/setup" - bin_setup = IO.read(bin_setup_path) - - expect(bin_setup).to assert_access_to_heroku_app("#{app_name}-production") - expect(bin_setup).to assert_access_to_heroku_app("#{app_name}-staging") - expect(bin_setup).to match(/^git config heroku.remote staging/) - expect("bin/setup").to be_executable - - readme = IO.read("#{project_path}/README.md") - - expect(readme).to include("./bin/deploy staging") - expect(readme).to include("./bin/deploy production") - end - end - - context "--heroku with region flag" do - before(:all) do - clean_up - run_suspenders(%(--heroku=true --heroku-flags="--region eu")) - setup_app_dependencies - end - - it "suspends a project with extra Heroku flags" do - expect(FakeHeroku).to have_created_app_for("staging", "--region eu") - expect(FakeHeroku).to have_created_app_for("production", "--region eu") - end - end - - def assert_access_to_heroku_app(app_name) - match(/^if heroku apps:info --app #{app_name}/) - end - - def clean_up - drop_dummy_database - clear_tmp_directory - end -end diff --git a/spec/features/new_project_spec.rb b/spec/features/new_project_spec.rb deleted file mode 100644 index f232b958e..000000000 --- a/spec/features/new_project_spec.rb +++ /dev/null @@ -1,344 +0,0 @@ -require "spec_helper" - -RSpec.describe "Suspend a new project with default configuration", type: :feature do - before(:all) do - drop_dummy_database - clear_tmp_directory - run_suspenders - setup_app_dependencies - end - - it "uses custom Gemfile" do - gemfile_file = IO.read("#{project_path}/Gemfile") - expect(gemfile_file).to match( - /^ruby "#{RUBY_VERSION}"$/o - ) - expect(gemfile_file).to match( - /^gem "rails", "#{Suspenders::RAILS_VERSION}"$/o - ) - end - - it "ensures project specs pass" do - Dir.chdir(project_path) do - Bundler.with_unbundled_env do - expect(`rake`).to include("0 failures") - end - end - end - - it "includes the bundle:audit task" do - Dir.chdir(project_path) do - Bundler.with_unbundled_env do - expect(`rails -T`).to include("rails bundle:audit") - end - end - end - - it "creates .ruby-version with the running ruby version" do - ruby_version_file = project_path.join(".ruby-version").read - - expect(ruby_version_file).to eq "#{RUBY_VERSION}\n" - end - - it "copies dotfiles" do - expect(File).to exist("#{project_path}/.sample.env") - end - - it "doesn't generate test directory" do - expect(File).not_to exist("#{project_path}/test") - end - - it "loads secret_key_base from env" do - secrets_file = IO.read("#{project_path}/config/secrets.yml") - - expect(secrets_file) - .to match(/secret_key_base: <%= ENV\["SECRET_KEY_BASE"\] %>/) - end - - it "adds bin/setup file" do - expect(File).to exist("#{project_path}/bin/setup") - end - - it "makes bin/setup executable" do - expect("bin/setup").to be_executable - end - - it "adds bin/yarn file" do - expect(File).to exist("#{project_path}/bin/yarn") - end - - it "makes bin/setup executable" do - expect("bin/yarn").to be_executable - end - - it "adds support file for action mailer" do - expect(File).to exist("#{project_path}/spec/support/action_mailer.rb") - end - - it "configures capybara-chromedriver" do - expect(File).to exist("#{project_path}/spec/support/chromedriver.rb") - end - - it "adds support file for i18n" do - expect(File).to exist("#{project_path}/spec/support/i18n.rb") - end - - it "creates good default .hound.yml" do - hound_config_file = IO.read("#{project_path}/.hound.yml") - - expect(hound_config_file).to include "enabled: true" - end - - it "initializes ActiveJob to avoid memory bloat" do - expect(File) - .to exist("#{project_path}/config/initializers/active_job.rb") - end - - it "records pageviews through Segment if ENV variable set" do - expect(analytics_partial) - .to include(%(<% if ENV["SEGMENT_KEY"] %>)) - expect(analytics_partial) - .to include(%{analytics.load("<%= ENV["SEGMENT_KEY"] %>");}) - end - - it "raises on unpermitted parameters in all environments" do - result = IO.read("#{project_path}/config/application.rb") - - expect(result).to match( - /^ +config.action_controller.action_on_unpermitted_parameters = :raise$/ - ) - end - - it "adds explicit quiet_assets configuration" do - result = IO.read("#{project_path}/config/application.rb") - - expect(result).to match(/^ +config.assets.quiet = true$/) - end - - it "configures public_file_server.headers in production" do - expect(production_config).to match( - /^ +config.public_file_server.headers = {\n +"Cache-Control" => "public,/ - ) - end - - it "configures production environment to enforce SSL" do - expect(production_config).to match( - /^ +config.force_ssl = true/ - ) - end - - it "raises on missing translations in development and test" do - [development_config, test_config].each do |environment_file| - expect(environment_file).to match( - /^ +config.i18n.raise_on_missing_translations = true$/ - ) - end - end - - it "evaluates en.yml.erb" do - locales_en_file = IO.read("#{project_path}/config/locales/en.yml") - - expect(locales_en_file).to match(/application: #{app_name.humanize}/) - end - - it "configs simple_form" do - expect(File).to exist("#{project_path}/config/initializers/simple_form.rb") - end - - it "configs :test email delivery method for development" do - expect(development_config) - .to match(/^ +config.action_mailer.delivery_method = :file$/) - end - - it "sets action mailer default host and asset host" do - config_key = "config.action_mailer.asset_host" - # rubocop:disable Lint/InterpolationCheck - config_value = - %q{"https://#{ENV\.fetch\("ASSET_HOST", ENV\.fetch\("APPLICATION_HOST"\)\)}} - # rubocop:enable Lint/InterpolationCheck - expect(production_config).to match(/#{config_key} = #{config_value}/) - end - - it "uses APPLICATION_HOST, not HOST in the production config" do - expect(production_config).to match(/"APPLICATION_HOST"/) - expect(production_config).not_to match(/"HOST"/) - end - - it "configures email interceptor" do - email_file = File.join(project_path, "config", "initializers", "email.rb") - email_config = IO.read(email_file) - - expect(email_config) - .to include(%{RecipientInterceptor.new(ENV["EMAIL_RECIPIENTS"])}) - end - - it "configures language in html element" do - layout_path = "/app/views/layouts/application.html.erb" - layout_file = IO.read("#{project_path}#{layout_path}") - expect(layout_file).to match(//) - end - - it "configures requests specs" do - application_config = IO.read("#{project_path}/config/application.rb") - - expect(application_config).to match( - /^ +generate.request_specs true$/ - ) - end - - it "configs active job queue adapter" do - application_config = IO.read("#{project_path}/config/application.rb") - - expect(application_config).to match(/^ +config.active_job.queue_adapter = :sidekiq$/) & - match(/^ +config.action_mailer.deliver_later_queue_name = nil$/) & - match(/^ +config.action_mailbox.queues.routing = nil$/) & - match(/^ +config.active_storage.queues.analysis = nil$/) & - match(/^ +config.active_storage.queues.purge = nil$/) & - match(/^ +config.active_storage.queues.mirror = nil$/) - expect(test_config).to match( - /^ +config.active_job.queue_adapter = :inline$/ - ) - end - - it "configs bullet gem in development" do - expect(development_config).to match(/^ +Bullet.enable = true$/) - expect(development_config).to match(/^ +Bullet.bullet_logger = true$/) - expect(development_config).to match(/^ +Bullet.rails_logger = true$/) - # prevent broken result of standard removing whitespaces - expect(development_config).to_not match(/trueconfig/) - end - - it "configs missing assets to raise in test" do - expect(test_config).to match( - /^ +config.assets.raise_runtime_errors = true$/ - ) - end - - it "removes comments and extra newlines from config files" do - config_files = [ - IO.read("#{project_path}/config/application.rb"), - IO.read("#{project_path}/config/environment.rb"), - development_config, - test_config, - production_config - ] - - config_files.each do |file| - expect(file).not_to match(/^\s*#.*$/) - expect(file).not_to eq(file.strip) - expect(file).not_to match(%r{^$\n\n}) - end - end - - it "copies factories.rb" do - expect(File).to exist("#{project_path}/spec/factories.rb") - end - - it "creates review apps setup script" do - bin_setup_path = "#{project_path}/bin/setup_review_app" - bin_setup = IO.read(bin_setup_path) - - expect(bin_setup).to include("PARENT_APP_NAME=#{app_name.dasherize}-staging") - expect(bin_setup).to include("APP_NAME=#{app_name.dasherize}-staging-pr-$1") - expect(bin_setup).to include("heroku ps:scale worker=1 --app $APP_NAME") - expect(bin_setup).to include("heroku restart --app $APP_NAME") - - expect("bin/setup_review_app").to be_executable - end - - it "creates deploy script" do - bin_deploy_path = "#{project_path}/bin/deploy" - bin_deploy = IO.read(bin_deploy_path) - - expect(bin_deploy).to include("git push") - expect("bin/deploy").to be_executable - end - - it "creates heroku application manifest file with application name in it" do - app_json_file = IO.read("#{project_path}/app.json") - - expect(app_json_file).to match(/"name":\s*"#{app_name.dasherize}"/) - end - - it "adds high_voltage" do - gemfile = IO.read("#{project_path}/Gemfile") - expect(gemfile).to match(/high_voltage/) - end - - it "adds sassc-rails" do - gemfile = read_project_file("Gemfile") - - expect(gemfile).to match(/sassc-rails/) - end - - it "configures Timecop safe mode" do - spec_helper = read_project_file(%w[spec spec_helper.rb]) - expect(spec_helper).to match(/Timecop.safe_mode = true/) - end - - it "adds and configures a bundler strategy for css and js" do - gemfile = read_project_file("Gemfile") - - expect(gemfile).to match(/cssbundling-rails/) - expect(gemfile).to match(/jsbundling-rails/) - expect(File).to exist("#{project_path}/postcss.config.js") - expect(File).to exist("#{project_path}/package.json") - expect(File).to exist("#{project_path}/bin/dev") - expect(File).to exist("#{project_path}/app/assets/stylesheets/application.postcss.css") - expect(File).to exist("#{project_path}/app/javascript/application.js") - end - - it "adds normalize.css" do - stylesheet = read_project_file %w[app assets stylesheets application.postcss.css] - dependencies = read_project_file %w[package.json] - configuration = read_project_file %w[postcss.config.js] - - expect(stylesheet).to include(%(@import "normalize.css")) - expect(dependencies).to include(%("postcss-normalize")) - expect(configuration).to include(%(require('postcss-normalize'))) - end - - it "imports css and js" do - layout = read_project_file %w[app views layouts application.html.erb] - - expect(layout) - .to include(%(<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>)) - expect(layout) - .to include(%(<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>)) - end - - it "loads security helpers" do - layout = read_project_file %w[app views layouts application.html.erb] - - expect(layout) - .to include(%(<%= csp_meta_tag %>)) - expect(layout) - .to include(%(<%= csrf_meta_tags %>)) - end - - def app_name - TestPaths::APP_NAME - end - - def development_config - @_development_config ||= - read_project_file %w[config environments development.rb] - end - - def test_config - @_test_config ||= read_project_file %w[config environments test.rb] - end - - def production_config - @_production_config ||= - read_project_file %w[config environments production.rb] - end - - def analytics_partial - IO.read("#{project_path}/app/views/application/_analytics.html.erb") - end - - def read_project_file(path) - IO.read(File.join(project_path, *path)) - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index e2f99460a..000000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "bundler/setup" - -Bundler.require(:default, :test) - -require (Pathname.new(__FILE__).dirname + "../lib/suspenders").expand_path - -Dir["./spec/support/*.rb"].sort.each { |file| require file } - -RSpec.configure do |config| - config.include FeatureTestHelpers, type: :feature - config.include GeneratorTestHelpers, type: :generator - - config.before(:all) do - FileOperations.create_tmp_directory - EnvPath.prepend_env_path!(TestPaths.fake_bin_path) - end -end diff --git a/spec/support/be_executable_matcher.rb b/spec/support/be_executable_matcher.rb deleted file mode 100644 index edf55d6ca..000000000 --- a/spec/support/be_executable_matcher.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -RSpec::Matchers.define :be_executable do - match do |filename| - TestPaths.app_path.join(filename).executable? - end -end diff --git a/spec/support/contain_json_matcher.rb b/spec/support/contain_json_matcher.rb deleted file mode 100644 index eeb19ccb6..000000000 --- a/spec/support/contain_json_matcher.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require "json" - -RSpec::Matchers.define :contain_json do - match do - @sub_json = expected - @filename = actual - - filepath = TestPaths.app_path.join(@filename) - @json = JSON.parse(filepath.read, symbolize_names: true) - - subhash?(@sub_json, @json) - end - - failure_message do - "in #{@filename}, expected to find\n#{@sub_json.inspect}\n" \ - "in\n#{@json.inspect}" - end - - private - - def subhash?(inner, outer) - if inner.is_a?(Hash) && outer.is_a?(Hash) - inner.all? { |key, value| subhash?(value, outer[key]) } - else - inner == outer - end - end -end diff --git a/spec/support/env_path.rb b/spec/support/env_path.rb deleted file mode 100644 index 0b790897a..000000000 --- a/spec/support/env_path.rb +++ /dev/null @@ -1,19 +0,0 @@ -module EnvPath - module_function - - def prepend_env_path!(path) - ENV["PATH"] = prepend_env_path(path) - end - - def prepend_env_path(path) - "#{path}:#{ENV["PATH"]}" - end - - def with_prepended_env_path(path) - old_path = ENV["PATH"] - ENV["PATH"] = prepend_env_path(path) - yield ENV["PATH"] - ensure - ENV["PATH"] = old_path - end -end diff --git a/spec/support/exist_as_a_file_matcher.rb b/spec/support/exist_as_a_file_matcher.rb deleted file mode 100644 index 4f8f032f7..000000000 --- a/spec/support/exist_as_a_file_matcher.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -RSpec::Matchers.define :exist_as_a_file do - match do |filename| - TestPaths.app_path.join(filename).exist? - end -end diff --git a/spec/support/fake_bundler.rb b/spec/support/fake_bundler.rb deleted file mode 100644 index b943a3025..000000000 --- a/spec/support/fake_bundler.rb +++ /dev/null @@ -1,55 +0,0 @@ -require "pathname" -require "json" - -class FakeBundler - TAPE = Pathname(__dir__).join("..", "..", "tmp", "bundler_info") - - def self.stub_unbundled_env!(spec, path:) - spec.instance_eval do - allow(Bundler).to receive(:unbundled_env).and_return( - Bundler.unbundled_env.merge( - "PATH" => path, - "RAN_WITH_UNBUNDLED_ENV" => "true" - ) - ) - end - end - - def record! - run_info = JSON.dump( - given_args: ARGV.join(" "), - gemfile_snapshot: File.read("Gemfile"), - has_unbundled_env: ENV["RAN_WITH_UNBUNDLED_ENV"] - ) - - File.write(TAPE, run_info) - end - - def ran? - !run_info.empty? - end - - def given_args - run_info["given_args"] - end - - def bundled_gemfile - run_info["gemfile_snapshot"] - end - - def unbundled_env? - run_info["has_unbundled_env"] - end - - private - - def run_info - @run_info ||= JSON.parse(File.read(TAPE)) - rescue Errno::ENOENT, JSON::ParserError - warn <<~MSG - Could not find #{TAPE.basename} file! - Fake bundler either did not run or the JSON from it is invalid. - MSG - {} - end -end diff --git a/spec/support/fake_bundler_matchers.rb b/spec/support/fake_bundler_matchers.rb deleted file mode 100644 index f183a77ac..000000000 --- a/spec/support/fake_bundler_matchers.rb +++ /dev/null @@ -1,58 +0,0 @@ -# FakeBundler records bundler information through a fake "bundler" -# binary. This RSpec matcher relies on that functionality. -RSpec::Matchers.define :have_bundled do |expected_bundler_args = ""| - match do |file_str| - raise 'Use expect("Gemfile")' if file_str != "Gemfile" - - fake_bundler = FakeBundler.new - - @ran_bundler = fake_bundler.ran? - @with_unbundled_env = fake_bundler.unbundled_env? - @actual_bundler_args = fake_bundler.given_args - @unexpected_bundler_args = expected_bundler_args != fake_bundler.given_args - @bundled_gemfile = fake_bundler.bundled_gemfile - - if !@ran_bundler || !@with_unbundled_env || @unexpected_bundler_args - false - elsif @gemfile_matching - @bundled_gemfile.match?(@gemfile_matching) - else - true - end - end - - chain :matching do |regex| - @gemfile_matching = regex - end - - failure_message do - if !@ran_bundler - "The generator did not call bundler!" - elsif !@with_unbundled_env - <<~MSG - Bundler was executed, but not with an unbundled env! - Make sure to run your bundler command like this: - - Bundler.with_unbundled_env { run "bundle #{expected_bundler_args}" } - MSG - elsif @unexpected_bundler_args - wrap_args = ->(args) { args.empty? ? "no args" : %("#{args}") } - - actual = wrap_args.call(@actual_bundler_args) - expected = wrap_args.call(expected_bundler_args) - - <<~MSG - Bundler was given unexpected arguments. - Expected #{expected} but got #{actual} - MSG - elsif @gemfile_matching - <<~MSG - Gemfile does not match the given pattern! - - #{@bundled_gemfile} - MSG - end - end -end - -RSpec::Matchers.define_negated_matcher :not_have_bundled, :have_bundled diff --git a/spec/support/fake_github.rb b/spec/support/fake_github.rb deleted file mode 100644 index c70e1ba2c..000000000 --- a/spec/support/fake_github.rb +++ /dev/null @@ -1,17 +0,0 @@ -class FakeGithub - RECORDER = File.expand_path(File.join("..", "..", "tmp", "hub_commands"), File.dirname(__FILE__)) - - def initialize(args) - @args = args - end - - def run! - File.open(RECORDER, "a") do |file| - file.write @args.join(" ") - end - end - - def self.has_created_repo?(repo_name) - File.read(RECORDER) == "create #{repo_name}" - end -end diff --git a/spec/support/fake_heroku.rb b/spec/support/fake_heroku.rb deleted file mode 100644 index c814d3b0f..000000000 --- a/spec/support/fake_heroku.rb +++ /dev/null @@ -1,49 +0,0 @@ -class FakeHeroku - RECORDER = File.expand_path(File.join("..", "..", "tmp", "heroku_commands"), File.dirname(__FILE__)) - - def initialize(args) - @args = args - end - - def run! - if @args.first == "help" - puts "pipelines # manage collections of apps in pipelines" - end - File.open(RECORDER, "a") do |file| - file.puts @args.join(" ") - end - end - - def self.has_gem_included?(project_path, gem_name) - gemfile = File.open(File.join(project_path, "Gemfile"), "a") - - File.foreach(gemfile).any? do |line| - line.match(/#{Regexp.quote(gem_name)}/) - end - end - - def self.has_created_app_for?(environment, flags = nil) - app_name = "#{TestPaths::APP_NAME.dasherize}-#{environment}" - - command = if flags - "create #{app_name} #{flags} --remote #{environment}\n" - else - "create #{app_name} --remote #{environment}\n" - end - - File.foreach(RECORDER).any? { |line| line == command } - end - - def self.has_configured_vars?(remote_name, var) - commands_ran =~ /^config:add #{var}=.+ --remote #{remote_name}\n/ - end - - def self.has_setup_pipeline_for?(app_name) - commands_ran =~ /^pipelines:create #{app_name} -a #{app_name}-staging --stage staging/ && - commands_ran =~ /^pipelines:add #{app_name} -a #{app_name}-production --stage production/ - end - - def self.commands_ran - @commands_ran ||= File.read(RECORDER) - end -end diff --git a/spec/support/fake_yarn.rb b/spec/support/fake_yarn.rb deleted file mode 100644 index 1d6770f9c..000000000 --- a/spec/support/fake_yarn.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "pathname" - -class FakeYarn - TAPE = Pathname(__dir__).join("..", "..", "tmp", "yarn_info") - - def record! - File.write(TAPE, ARGV.join(" ")) - end - - def ran? - !arguments.empty? - end - - def arguments - @arguments ||= File.read(TAPE) - rescue Errno::ENOENT - warn <<~MSG - Could not find #{TAPE.basename} file! - Fake yarn did not run. - MSG - - "" - end -end diff --git a/spec/support/fake_yarn_matchers.rb b/spec/support/fake_yarn_matchers.rb deleted file mode 100644 index 81cb74f0d..000000000 --- a/spec/support/fake_yarn_matchers.rb +++ /dev/null @@ -1,25 +0,0 @@ -# FakeYarn records yarn information through a fake "bin/yarn" -# binary. This RSpec matcher relies on that functionality. -RSpec::Matchers.define :have_yarned do |expected_yarn_args = ""| - match do |file_str| - raise 'Use expect("package.json")' if file_str != "package.json" - - fake_yarn = FakeYarn.new - - @yarn_ran = fake_yarn.ran? - @actual_yarn_args = fake_yarn.arguments - - @yarn_ran && expected_yarn_args == @actual_yarn_args - end - - failure_message do - if !@yarn_ran - "The generator did not call yarn" - else - <<~MSG - Yarn was executed, but the given arguments are incorrect. - Expected "#{expected_yarn_args}" but got "#{@actual_yarn_args}" - MSG - end - end -end diff --git a/spec/support/fakes/bin/heroku b/spec/support/fakes/bin/heroku deleted file mode 100755 index 745c0b246..000000000 --- a/spec/support/fakes/bin/heroku +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby - -require "pathname" -require Pathname(__dir__) / ".." / ".." / "fake_heroku" - -FakeHeroku.new(ARGV).run! diff --git a/spec/support/fakes/bin/hub b/spec/support/fakes/bin/hub deleted file mode 100755 index 318401b34..000000000 --- a/spec/support/fakes/bin/hub +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby - -require "pathname" -require Pathname(__dir__) / ".." / ".." / "fake_github" - -FakeGithub.new(ARGV).run! diff --git a/spec/support/fakes/bundler/audit/task.rb b/spec/support/fakes/bundler/audit/task.rb deleted file mode 100644 index 372c6cacb..000000000 --- a/spec/support/fakes/bundler/audit/task.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "pathname" - -load Pathname(__dir__) / ".." / ".." / ".." / "message_matcher.rb" - -module Bundler - module Audit - Task = MessageMatcher.new(message: [:new]) do - puts "Fake task loaded" - end - end -end diff --git a/spec/support/fakes/bundler_bin/bundle b/spec/support/fakes/bundler_bin/bundle deleted file mode 100755 index 54b1aad5a..000000000 --- a/spec/support/fakes/bundler_bin/bundle +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby - -require "pathname" -require Pathname(__dir__) / ".." / ".." / "fake_bundler" - -FakeBundler.new.record! diff --git a/spec/support/fakes/fake_rails.rb b/spec/support/fakes/fake_rails.rb deleted file mode 100644 index 7e8b1c77d..000000000 --- a/spec/support/fakes/fake_rails.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Rails - RAILS_ENV = ENV.fetch("RAILS_ENV", "development") - - class Env < String - def development? - self == "development" - end - - def test? - self == "test" - end - - def production? - self == "production" - end - end - - def self.env - @env ||= Env.new(RAILS_ENV) - end -end diff --git a/spec/support/feature_test_helpers.rb b/spec/support/feature_test_helpers.rb deleted file mode 100644 index cc6258557..000000000 --- a/spec/support/feature_test_helpers.rb +++ /dev/null @@ -1,181 +0,0 @@ -require "English" -require_relative "env_path" -require_relative "file_operations" -require_relative "test_paths" - -module FeatureTestHelpers - include TestPaths - include FileOperations - - def remove_project_directory - FileUtils.rm_rf(project_path) - end - - def run_suspenders(arguments = nil) - run_in_tmp do - EnvPath.prepend_env_path!(fake_bin_path) - command = "#{suspenders_bin} #{APP_NAME} #{arguments}" - - with_revision_for_honeybadger do - result = `#{command}` - debug result - end - - yield command if block_given? - - Dir.chdir(APP_NAME) do - commit_all - end - end - end - - def run_suspenders!(*args) - run_suspenders(*args) do |command| - if $CHILD_STATUS.exitstatus.nonzero? - raise <<~MESSAGE - Suspenders failed. To debug, generate an app with: - - #{command} - - Or run rspec with SHOW_DEBUG=true to display the full output. - MESSAGE - end - end - end - - def with_app - drop_dummy_database - remove_project_directory - rails_new - setup_app_dependencies - - yield - end - - def rails_new - run_in_tmp do - EnvPath.prepend_env_path!(fake_bin_path) - - with_revision_for_honeybadger do - debug `#{system_rails_bin} new #{APP_NAME} --skip-spring -d postgresql -m #{rails_template_path}` - end - - Dir.chdir(APP_NAME) do - commit_all - end - end - end - - def generate(generator) - run_in_project do - with_revision_for_honeybadger do - debug `#{project_rails_bin} generate #{generator}` - end - end - end - - def destroy(generator) - run_in_project do - with_revision_for_honeybadger do - debug `#{project_rails_bin} destroy #{generator}` - end - end - end - - def suspenders_help_command - run_in_tmp do - debug `#{suspenders_bin} -h` - end - end - - def setup_app_dependencies - run_in_project do - debug `bundle check || bundle install` - end - rescue Errno::ENOENT - # The project_path might not exist, in which case we can skip this. - end - - def drop_dummy_database - run_in_project do - debug `#{project_rails_bin} db:drop 2>&1` - end - rescue Errno::ENOENT - # The project_path might not exist, in which case we can skip this. - end - - def usage_file - @usage_path ||= File.join(root_path, "USAGE") - end - - private - - def suspenders_bin - File.join(root_path, "bin", "suspenders") - end - - def system_rails_bin - "rails" - end - - def project_rails_bin - "bin/rails" - end - - def rails_template_path - root_path.join("spec", "support", "rails_template.rb") - end - - def commit_all - with_env("HOME", tmp_path) do - debug `git config user.email suspenders@example.com` - debug `git config user.name "Suspenders Boy"` - debug `git add .` - debug `git commit -m 'Initial commit'` - end - end - - def with_env(name, new_value) - had_key = ENV.has_key?(name) - prior = ENV[name] - ENV[name] = new_value.to_s - - yield - ensure - ENV.delete(name) - - if had_key - ENV[name] = prior - end - end - - def with_revision_for_honeybadger - with_env("HEROKU_SLUG_COMMIT", 1) do - yield - end - end - - def run_in_tmp - Dir.chdir(tmp_path) do - Bundler.with_unbundled_env do - yield - end - end - end - - def run_in_project - Dir.chdir(project_path) do - Bundler.with_unbundled_env do - yield - end - end - end - - def debug(output) - if ENV["SHOW_DEBUG"] - warn output - end - - output - end -end diff --git a/spec/support/file_operations.rb b/spec/support/file_operations.rb deleted file mode 100644 index 45aa22e7f..000000000 --- a/spec/support/file_operations.rb +++ /dev/null @@ -1,34 +0,0 @@ -module FileOperations - module_function - - def read_file(file) - TestPaths.app_path.join(file).read - end - - def touch_file(file) - path = app_path.join(file) - path.join("..").mkpath - - FileUtils.touch(TestPaths.app_path.join(file)) - end - - def rm_file(file) - FileUtils.rm_rf(TestPaths.app_path.join(file)) - end - - def copy_file(source_file, destination_file) - source_path = TestPaths.template_path.join(source_file) - destination_path = TestPaths.app_path.join(destination_file) - - destination_path.join("..").mkpath - FileUtils.cp(source_path, destination_path) - end - - def create_tmp_directory - FileUtils.mkdir_p(TestPaths.tmp_path) - end - - def clear_tmp_directory - FileUtils.rm_rf(Dir[TestPaths.tmp_path / "*"]) - end -end diff --git a/spec/support/fixtures/dummy_app/Gemfile b/spec/support/fixtures/dummy_app/Gemfile deleted file mode 100644 index 7d2962eb5..000000000 --- a/spec/support/fixtures/dummy_app/Gemfile +++ /dev/null @@ -1,7 +0,0 @@ -# This file is part of our fake Rails app, for testing purposes -source "https://rubygems.org" - -git_source(:github) do |repo_name| - repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") - "https://github.com/#{repo_name}.git" -end diff --git a/spec/support/fixtures/dummy_app/Rakefile b/spec/support/fixtures/dummy_app/Rakefile deleted file mode 100644 index 75e483b12..000000000 --- a/spec/support/fixtures/dummy_app/Rakefile +++ /dev/null @@ -1,8 +0,0 @@ -# This file is part of our fake Rails app, for testing purposes -require "pathname" - -path = Pathname(__dir__) / "lib" / "tasks" / "**" / "*.rake" - -Pathname.glob(path).each do |file| - load file -end diff --git a/spec/support/fixtures/dummy_app/bin/yarn b/spec/support/fixtures/dummy_app/bin/yarn deleted file mode 100755 index 11f3e4158..000000000 --- a/spec/support/fixtures/dummy_app/bin/yarn +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env ruby - -require "pathname" -require Pathname(__dir__) / ".." / ".." / ".." / "spec" / "support" / "fake_yarn" - -FakeYarn.new.record! diff --git a/spec/support/fixtures/dummy_app/config/environments/development.rb b/spec/support/fixtures/dummy_app/config/environments/development.rb deleted file mode 100644 index eae7b883a..000000000 --- a/spec/support/fixtures/dummy_app/config/environments/development.rb +++ /dev/null @@ -1,28 +0,0 @@ -# This file is part of our fake Rails app, for testing purposes -Rails.application.configure do - config.cache_classes = false - config.eager_load = false - config.consider_all_requests_local = true - if Rails.root.join("tmp", "caching-dev.txt").exist? - config.action_controller.perform_caching = true - config.action_controller.enable_fragment_cache_logging = true - config.cache_store = :memory_store - config.public_file_server.headers = {} - else - config.action_controller.perform_caching = false - config.cache_store = :null_store - end - config.active_storage.service = :local - config.action_mailer.raise_delivery_errors = true - config.action_mailer.delivery_method = :file - config.action_mailer.perform_caching = false - config.active_support.deprecation = :log - config.active_record.migration_error = :page_load - config.active_record.verbose_query_logs = true - config.assets.debug = true - config.assets.quiet = true - config.action_view.raise_on_missing_translations = true - config.file_watcher = ActiveSupport::EventedFileUpdateChecker - config.action_mailer.default_url_options = {host: "localhost:3000"} - config.action_mailer.asset_host = "http://localhost:3000" -end diff --git a/spec/support/fixtures/dummy_app/config/environments/production.rb b/spec/support/fixtures/dummy_app/config/environments/production.rb deleted file mode 100644 index 07ab23832..000000000 --- a/spec/support/fixtures/dummy_app/config/environments/production.rb +++ /dev/null @@ -1,24 +0,0 @@ -# This file is part of our fake Rails app, for testing purposes -Rails.application.configure do - config.cache_classes = true - config.eager_load = true - config.consider_all_requests_local = false - config.action_controller.perform_caching = true - config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? - config.assets.compile = false - config.active_storage.service = :local - config.log_level = :debug - config.log_tags = [:request_id] - config.action_mailer.perform_caching = false - config.i18n.fallbacks = true - config.active_support.deprecation = :notify - config.log_formatter = ::Logger::Formatter.new - - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new($stdout) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - - config.active_record.dump_schema_after_migration = false -end diff --git a/spec/support/generator_matchers.rb b/spec/support/generator_matchers.rb deleted file mode 100644 index c2bcb34c8..000000000 --- a/spec/support/generator_matchers.rb +++ /dev/null @@ -1,45 +0,0 @@ -RSpec::Matchers.define :match_original_file do - match do |path| - @path = path - @original_contents = TestPaths.fake_app_fixture_path.join(path).read - @actual_contents = TestPaths.app_path.join(path).read - - @original_contents == @actual_contents - end - - failure_message do - <<~MESSAGE - #{@path} does not match original file. The diff is: - #{differ.diff_as_string(@actual_contents, @original_contents)} - MESSAGE - end - - def differ - RSpec::Support::Differ.new( - object_preparer: lambda do |object| - RSpec::Matchers::Composable.surface_descriptions_in(object) - end, - color: RSpec::Matchers.configuration.color? - ) - end -end - -RSpec::Matchers.define :have_syntax_error do - # rubocop:disable Lint/RescueException - match do |path| - @path = path - load TestPaths.app_path.join(path) - false - rescue SyntaxError - true - rescue Exception - false - end - # rubocop:enable Lint/RescueException - - failure_message do - "The file #{@path} has NO syntax errors" - end -end - -RSpec::Matchers.define_negated_matcher :have_no_syntax_error, :have_syntax_error diff --git a/spec/support/generator_test_helpers.rb b/spec/support/generator_test_helpers.rb deleted file mode 100644 index a9e5f0629..000000000 --- a/spec/support/generator_test_helpers.rb +++ /dev/null @@ -1,71 +0,0 @@ -require_relative "test_paths" -require_relative "file_operations" - -module GeneratorTestHelpers - include TestPaths - include FileOperations - - def invoke!(klass, *args, **kwargs, &block) - instance_eval(&block) if block - call_generator!(new_invoke_generator(klass, *args, **kwargs)) - end - - def revoke!(klass, *args, **kwargs) - call_generator!(new_revoke_generator(klass, *args, **kwargs)) - end - - def invoke_then_revoke!(klass, *args, **kwargs) - invoke! klass, *args, **kwargs - revoke! klass, *args, **kwargs - end - - def call_generator!(generator) - generator.invoke_all - generator - end - - def new_invoke_generator(klass, *args) - new_generator(klass, *args, behavior: :invoke) - end - - def new_revoke_generator(klass, *args) - new_generator(klass, *args, behavior: :revoke) - end - - def new_generator(klass, *args, **opts) - klass.new(args, [], destination_root: app_path, **opts) - end - - def with_fake_app - EnvPath.with_prepended_env_path(fake_bundler_bin_path) do |path| - FakeBundler.stub_unbundled_env!(self, path: path) - - execute = lambda do - clear_tmp_directory - create_fake_app_dir - Dir.chdir(app_path) { yield } - end - - if @no_silence - execute.call - else - OutputStub.silence { execute.call } - end - end - end - - # This allows turning off output redirection per spec if you need to - # debug or use a debugger such as pry - def no_silence! - @no_silence = true - end - - def create_fake_app_dir - FileUtils.cp_r fake_app_fixture_path, app_path - copy_file "spec_helper.rb", "spec/spec_helper.rb" - end - - def destroy_fake_app_dir - FileUtils.rm_rf tmp_path.join(APP_NAME) - end -end diff --git a/spec/support/match_contents_matcher.rb b/spec/support/match_contents_matcher.rb deleted file mode 100644 index a8b7f84e1..000000000 --- a/spec/support/match_contents_matcher.rb +++ /dev/null @@ -1,20 +0,0 @@ -RSpec::Matchers.define :match_contents do |regexp| - def file_contents(filename) - TestPaths.app_path.join(filename).read - end - - match do |filename| - file_contents(filename) =~ regexp - end - - failure_message do |filename| - <<~MESSAGE - #{filename} does not match the regex #{regexp}. - The contents for #{filename} are: - - #{file_contents(filename)} - MESSAGE - end -end - -RSpec::Matchers.define_negated_matcher :not_match_contents, :match_contents diff --git a/spec/support/message_matcher.rb b/spec/support/message_matcher.rb deleted file mode 100644 index 5013da487..000000000 --- a/spec/support/message_matcher.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "pathname" - -class MessageMatcher - def initialize(message:, &block) - @method, @args = message - @args ||= [] - @block = block || raise("Needs a block!") - end - - def method_missing(method, *args, &block) - if method == @method && args == @args - @block.call - else - puts "Failed to match! Method: #{method}, args: #{args}" - end - end - - def respond_to_missing?(method, include_private = false) - method == @method - end -end diff --git a/spec/support/output_stub.rb b/spec/support/output_stub.rb deleted file mode 100644 index d1c073fe0..000000000 --- a/spec/support/output_stub.rb +++ /dev/null @@ -1,15 +0,0 @@ -module OutputStub - module_function - - def silence(output_device = File.new("/dev/null", "w"), &block) - original_stdout = $stdout - original_stderr = $stderr - - $stdout = $stderr = output_device - - yield block - ensure - $stdout = original_stdout - $stderr = original_stderr - end -end diff --git a/spec/support/rails_stub.rb b/spec/support/rails_stub.rb deleted file mode 100644 index 24568b698..000000000 --- a/spec/support/rails_stub.rb +++ /dev/null @@ -1,17 +0,0 @@ -module RailsStub - extend RSpec::Mocks::ExampleMethods - - module_function - - def stub_app_class(app_class_name: nil) - require "active_support/core_ext/module/introspection" - - fake_app_class = Class.new do - define_singleton_method(:name) do - app_class_name || "RandomApp::Application" - end - end - - allow(Rails).to receive(:app_class).and_return(fake_app_class) - end -end diff --git a/spec/support/rails_template.rb b/spec/support/rails_template.rb deleted file mode 100644 index 45fe8ea4c..000000000 --- a/spec/support/rails_template.rb +++ /dev/null @@ -1 +0,0 @@ -gem "suspenders", path: File.expand_path("../..", __dir__) diff --git a/spec/support/test_paths.rb b/spec/support/test_paths.rb deleted file mode 100644 index 3744e7e34..000000000 --- a/spec/support/test_paths.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module TestPaths - APP_NAME = "dummy_app" - - module_function - - def app_path - tmp_path.join(APP_NAME) - end - alias_method :project_path, :app_path - - def template_path - root_path.join("templates") - end - - def fake_app_fixture_path - root_path.join("spec", "support", "fixtures", APP_NAME) - end - - def fakes_path - root_path.join("spec", "support", "fakes") - end - - def fake_bin_path - fakes_path.join("bin") - end - - def fake_bundler_bin_path - fakes_path.join("bundler_bin") - end - - def tmp_path - @tmp_path ||= root_path.join("tmp") - end - - def root_path - @root_path ||= Pathname(__dir__).join("..", "..") - end -end diff --git a/spec/suspenders/actions/strip_comments_action_spec.rb b/spec/suspenders/actions/strip_comments_action_spec.rb deleted file mode 100644 index 0bca11dff..000000000 --- a/spec/suspenders/actions/strip_comments_action_spec.rb +++ /dev/null @@ -1,489 +0,0 @@ -require "spec_helper" -require "suspenders/actions/strip_comments_action" - -RSpec.describe Suspenders::Actions::StripCommentsAction do - describe ".call" do - it "removes a comment at indentation 0" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # Comment 1 - Rails.application.configure do - config.force_ssl = true - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.force_ssl = true - end - SOURCE - end - - it "removes a comment at indentation 2" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - # A comment - config.force_ssl = true - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.force_ssl = true - end - SOURCE - end - - it "removes two comments at indentation 2" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - # Comment 1 - # Comment 2 - config.force_ssl = true - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.force_ssl = true - end - SOURCE - end - - it "removes inline comments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - config.force_ssl = true # A comment here - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.force_ssl = true - end - SOURCE - end - - it "does not remove non-comments that could be confused as comments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - str = <<~STR - # Not a comment - STR - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - str = <<~STR - # Not a comment - STR - end - SOURCE - end - - it "preserves the newline at the end of the file" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # Comment 1 - Rails.application.configure do - config.force_ssl = true - end - SOURCE - - expect(source).to eq(<<~SOURCE) - Rails.application.configure do - config.force_ssl = true - end - SOURCE - end - - it "removes comments that delineate blocks of code" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # Comment 1 - Rails.application.configure do - # Comment 1 - config.force_ssl = true - config.cache_store = :null_store - - # Comment 2 - config.eager_load = true - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.force_ssl = true - config.cache_store = :null_store - config.eager_load = true - end - SOURCE - end - - it "removes blank lines with whitespace" do - source = <<~SOURCE - # One - config.n = true - #{" " * 10} - # Two - config.t = true - SOURCE - - source = Suspenders::Actions::StripCommentsAction.call(source) - - expect(source.chomp).to eq(<<~SOURCE.chomp) - config.n = true - config.t = true - SOURCE - end - - it "removes trailing whitespace" do - source = <<~SOURCE - method do - config.n = true#{" " * 5} - config.t = true - end - SOURCE - - source = Suspenders::Actions::StripCommentsAction.call(source) - - expect(source.chomp).to eq(<<~SOURCE.chomp) - method do - config.n = true - config.t = true - end - SOURCE - end - - it "removes a block of comments + newlines + other comments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - config.cache_classes = true - - # Comment 1 - - # Comment 2 - config.load_defaults 6.0 - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.cache_classes = true - - config.load_defaults 6.0 - end - SOURCE - end - - it "removes a block of comments + newlines + other comments, and joins assignments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - config.cache_classes = true - - # Comment 1 - - # Comment 2 - config.other = false - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.cache_classes = true - config.other = false - end - SOURCE - end - - it "removes a block of comments + newlines after indentation changes" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - Rails.application.configure do - # Comment 1 - - # Comment 2 - config.cache_classes = true - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - config.cache_classes = true - end - SOURCE - end - - it "removes bigger blocks of comments + newlines + other comments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - module Foobar - class Application < Rails::Application - # Comment here - config.load_defaults 6.0 - - # Coment here - # Comment here - - # Comment here - config.generators.system_tests = nil - end - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - module Foobar - class Application < Rails::Application - config.load_defaults 6.0 - - config.generators.system_tests = nil - end - end - SOURCE - end - - it "removes leading newlines from classes, modules, and blocks" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - module Mod\n\n - class MyClass\n\n - MyGem.application.configure do |config|\n\n - config.option1 = true - - config.option2 = false - end - end - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - module Mod - class MyClass - MyGem.application.configure do |config| - config.option1 = true - config.option2 = false - end - end - end - SOURCE - end - - it "removes comments and newlines from the beginning of the source" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # The test environment is used exclusively to run your application's - # test suite. - - Rails.application.configure do - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - Rails.application.configure do - end - SOURCE - end - - it "correctly handles removal of comments at indentation 0" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # First require - require_relative 'boot' - - require "rails" - # Pick the frameworks you want: - require "active_model/railtie" - require "active_job/railtie" - # require "rails/test_unit/railtie" - - # Require the gems listed in Gemfile, including any gems - # you've limited to :test, :development, or :production. - Bundler.require(*Rails.groups) - - module Foo - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - require_relative 'boot' - - require "rails" - require "active_model/railtie" - require "active_job/railtie" - - Bundler.require(*Rails.groups) - - module Foo - end - SOURCE - end - - it "does not join assignments that are not preceded by other assignments" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - config.after_initialize do - Bullet.rails_logger = true - end - - config.action_mailer.delivery_method = :file - - config.action_mailer.perform_caching = false - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - config.after_initialize do - Bullet.rails_logger = true - end - - config.action_mailer.delivery_method = :file - config.action_mailer.perform_caching = false - SOURCE - end - - it "handles nested begin correctly" do - # There's an implicit "begin" block encompassing the entire code - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - # Comment here - config.action_mailer.delivery_method = :file - - # Some comment - config.action_mailer.perform_caching = false - - begin - # Comment here - config.action_mailer.first_call = :file - - # Some comment - config.action_mailer.second_call = false - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - config.action_mailer.delivery_method = :file - config.action_mailer.perform_caching = false - - begin - config.action_mailer.first_call = :file - config.action_mailer.second_call = false - end - SOURCE - end - - it "handles nested blocks correctly" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - first_block do - config.action_mailer.delivery_method = :file - - # Some comment - config.action_mailer.perform_caching = false - - second_block do - # Comment here - config.action_mailer.delivery_method = :file - - # Some comment - config.action_mailer.perform_caching = false - end - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - first_block do - config.action_mailer.delivery_method = :file - config.action_mailer.perform_caching = false - - second_block do - config.action_mailer.delivery_method = :file - config.action_mailer.perform_caching = false - end - end - SOURCE - end - - it "removes blank lines before begin" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - begin - - foo.bar = 1 - - begin - - bar.bat = 2 - end - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - begin - foo.bar = 1 - - begin - bar.bat = 2 - end - end - SOURCE - end - - it "removes comments right before the 'end' of a begin" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - begin - foo.bar = 1 - - # A comment - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - begin - foo.bar = 1 - end - SOURCE - end - - it "removes comments right before the 'end' of a block" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - foo do |instance| - instance.bar = 1 - - # A comment - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - foo do |instance| - instance.bar = 1 - end - SOURCE - end - - it "removes comments right before the 'end' of a class" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - class Foo - class Bar - # Another comment - end - - # A comment - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - class Foo - class Bar - end - end - SOURCE - end - - it "removes comments right before the 'end' of a module" do - source = Suspenders::Actions::StripCommentsAction.call(<<~SOURCE) - module Foo - module Bar - # Another comment - end - - # A comment - end - SOURCE - - expect(source.chomp).to eq(<<~SOURCE.chomp) - module Foo - module Bar - end - end - SOURCE - end - end -end diff --git a/spec/suspenders/app_generator_spec.rb b/spec/suspenders/app_generator_spec.rb deleted file mode 100644 index 9e6c6b7db..000000000 --- a/spec/suspenders/app_generator_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::AppGenerator do - it "includes ExitOnFailure" do - expect(described_class.ancestors).to include(Suspenders::ExitOnFailure) - end -end diff --git a/spec/suspenders/exit_on_failure_spec.rb b/spec/suspenders/exit_on_failure_spec.rb deleted file mode 100644 index 54ba4fd09..000000000 --- a/spec/suspenders/exit_on_failure_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::ExitOnFailure do - def make_generator_class(&block) - Class.new Rails::Generators::AppBase do - include Suspenders::ExitOnFailure - - class_eval(&block) - end - end - - def generator_exit_status(generator_class) - pid = fork do - OutputStub.silence { generator_class.start } - end - - Process.wait(pid) - - $CHILD_STATUS.exitstatus.zero? ? :exit_success : :exit_failure - end - - it "exits with failure status on generator error" do - generator_class = make_generator_class do - def generator_task - copy_file "non_existing_file", "non_existing_destination" - end - end - - expect(generator_exit_status(generator_class)).to be :exit_failure - end - - it "exits with failure status on bundle command error" do - generator_class = make_generator_class do - def generator_task - bundle_command "non_existing_bundle_command 2> /dev/null" - end - end - - expect(generator_exit_status(generator_class)).to be :exit_failure - end -end diff --git a/spec/suspenders/generators/accessibility_generator_spec.rb b/spec/suspenders/generators/accessibility_generator_spec.rb deleted file mode 100644 index 614157498..000000000 --- a/spec/suspenders/generators/accessibility_generator_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::AccessibilityGenerator, type: :generator do - describe "invoke" do - it "bundles the capybara_accessibility_audit gem" do - with_fake_app do - invoke! Suspenders::AccessibilityGenerator - - expect("Gemfile") - .to have_bundled("install").matching(/capybara_accessibility_audit/) - .and have_no_syntax_error - end - end - - it "bundles the citizensadvice/capybara_accessible_selectors GitHub repository gem" do - with_fake_app do - invoke! Suspenders::AccessibilityGenerator - - expect("Gemfile") - .to have_bundled("install").matching(/capybara_accessible_selectors/) - .and have_no_syntax_error - end - end - end - - describe "revoke" do - it "removes the gems from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::AccessibilityGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - end -end diff --git a/spec/suspenders/generators/advisories_generator_spec.rb b/spec/suspenders/generators/advisories_generator_spec.rb deleted file mode 100644 index c675c5f5d..000000000 --- a/spec/suspenders/generators/advisories_generator_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::AdvisoriesGenerator, type: :generator do - describe "invoke" do - it "generates a bundler-audit rake task" do - with_fake_app do - invoke! Suspenders::AdvisoriesGenerator - - expect("lib/tasks/bundler_audit.rake") - .to have_no_syntax_error - .and(match_contents(/Bundler::Audit::Task.new/)) - end - end - - context "when rails env is development" do - it "the bundler-audit rake task can be executed" do - with_fake_app do - invoke! Suspenders::AdvisoriesGenerator - - expect(`RAILS_ENV=development rake -I#{fakes_path} -rfake_rails -T`) - .to eq("Fake task loaded\n") - end - end - end - - context "when rails env is test" do - it "the bundler-audit rake task can be executed" do - with_fake_app do - invoke! Suspenders::AdvisoriesGenerator - - expect(`RAILS_ENV=test rake -I#{fakes_path} -rfake_rails -T`) - .to eq("Fake task loaded\n") - end - end - end - - context "when rails env is production" do - it "the bundler-audit rake task can be executed" do - with_fake_app do - invoke! Suspenders::AdvisoriesGenerator - - expect(`RAILS_ENV=production rake -I#{fakes_path} -rfake_rails -T`) - .to be_empty - end - end - end - - it "bundles the bundler-audit gem" do - with_fake_app do - invoke! Suspenders::AdvisoriesGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(/bundler-audit/) - end - end - end - - describe "revoke" do - it "destroys the bundler-audit rake task" do - with_fake_app do - invoke_then_revoke! Suspenders::AdvisoriesGenerator - - expect("lib/tasks/bundler_audit.rake").not_to exist_as_a_file - end - end - - it "removes the bundler-audit gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::AdvisoriesGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - end -end diff --git a/spec/suspenders/generators/base_spec.rb b/spec/suspenders/generators/base_spec.rb deleted file mode 100644 index 46f876672..000000000 --- a/spec/suspenders/generators/base_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Generators::Base do - it "includes ExitOnFailure" do - expect(described_class.ancestors).to include(Suspenders::ExitOnFailure) - end -end diff --git a/spec/suspenders/generators/ci_generator_spec.rb b/spec/suspenders/generators/ci_generator_spec.rb deleted file mode 100644 index 63bd485a3..000000000 --- a/spec/suspenders/generators/ci_generator_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::CiGenerator, type: :generator do - describe "invoke" do - it "bundles the simplecov gem" do - with_fake_app do - invoke! Suspenders::CiGenerator - - expect("Gemfile").to have_bundled("install").matching(/simplecov/) - end - end - - it "creates a circle.yml file" do - with_fake_app do - invoke! Suspenders::CiGenerator - - expect("circle.yml").to exist_as_a_file - end - end - - context "when it is an rspec project" do - it "configures spec_helper.rb with SimpleCov" do - with_fake_app do - invoke! Suspenders::CiGenerator - - expect("spec/spec_helper.rb") - .to match_contents(/SimpleCov.coverage_dir/) - .and match_contents(/SimpleCov.start/) - .and have_no_syntax_error - end - end - end - - context "when it is a minitest project" do - it "configures test_helper.rb instead of spec_helper.rb" do - with_fake_app do - rm_file "spec/spec_helper.rb" - touch_file "test/test_helper.rb" - - invoke! Suspenders::CiGenerator - - expect("test/test_helper.rb") - .to match_contents(/SimpleCov.coverage_dir/) - .and match_contents(/SimpleCov.start/) - .and have_no_syntax_error - end - end - end - end - - describe "revoke" do - it "removes the simplecov gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::CiGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "destroys the circle.yml file" do - with_fake_app do - invoke_then_revoke! Suspenders::CiGenerator - - expect("circle.yml").not_to exist_as_a_file - end - end - - context "when it is an rspec project" do - it "removes SimpleCov configuration from spec_helper.rb" do - with_fake_app do - invoke_then_revoke! Suspenders::CiGenerator - - expect("spec/spec_helper.rb") - .to not_match_contents(/SimpleCov/) - .and have_no_syntax_error - end - end - end - - context "when it is a minitest project" do - it "removes SimpleCov configuration from test_helper.rb" do - with_fake_app do - rm_file "spec/spec_helper.rb" - touch_file "test/test_helper.rb" - - invoke_then_revoke! Suspenders::CiGenerator - - expect("test/test_helper.rb") - .to not_match_contents(/SimpleCov.coverage_dir/) - .and not_match_contents(/SimpleCov.start/) - .and have_no_syntax_error - end - end - end - end -end diff --git a/spec/suspenders/generators/db_optimizations_generator_spec.rb b/spec/suspenders/generators/db_optimizations_generator_spec.rb deleted file mode 100644 index f11bb0796..000000000 --- a/spec/suspenders/generators/db_optimizations_generator_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::DbOptimizationsGenerator, type: :generator do - describe "invoke" do - it "bundles the bullet gem" do - with_fake_app do - invoke! Suspenders::DbOptimizationsGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(/bullet/) - end - end - - it "configures development.rb with bullet" do - with_fake_app do - invoke! Suspenders::DbOptimizationsGenerator - - expect("config/environments/development.rb") - .to have_no_syntax_error - .and match_contents(/Bullet.enable/) - end - end - end - - describe "revoke" do - it "removes the bullet gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::DbOptimizationsGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "removes bullet configuration from development.rb" do - with_fake_app do - invoke_then_revoke! Suspenders::DbOptimizationsGenerator - - expect("config/environments/development.rb") - .to have_no_syntax_error - .and match_original_file - end - end - end -end diff --git a/spec/suspenders/generators/inline_svg_generator_spec.rb b/spec/suspenders/generators/inline_svg_generator_spec.rb deleted file mode 100644 index 23b38fb6b..000000000 --- a/spec/suspenders/generators/inline_svg_generator_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::InlineSvgGenerator, type: :generator do - describe "invoke" do - it "bundles the inline_svg gem" do - with_fake_app do - invoke! Suspenders::InlineSvgGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(/inline_svg/) - end - end - - it "creates an initializer for inline_svg" do - with_fake_app do - invoke! Suspenders::InlineSvgGenerator - - expect("config/initializers/inline_svg.rb") - .to have_no_syntax_error - .and match_contents(/InlineSvg/) - end - end - end - - describe "revoke" do - it "removes the inline_svg gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::InlineSvgGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "removes the inline_svg initializer" do - with_fake_app do - invoke_then_revoke! Suspenders::InlineSvgGenerator - - expect("config/initializers/inline_svg.rb").not_to exist_as_a_file - end - end - end -end diff --git a/spec/suspenders/generators/json_generator_spec.rb b/spec/suspenders/generators/json_generator_spec.rb deleted file mode 100644 index 35fa9bedd..000000000 --- a/spec/suspenders/generators/json_generator_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::JsonGenerator, type: :generator do - describe "invoke" do - it "bundles the oj gem" do - with_fake_app do - invoke! Suspenders::JsonGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(%r{gem .oj.}) - end - end - - it "creates an initializer for oj" do - with_fake_app do - invoke! Suspenders::JsonGenerator - - expect("config/initializers/oj.rb").to match_contents(/Oj.optimize_rails/) - end - end - end - - describe "revoke" do - it "removes the oj gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::JsonGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "destroys the oj initializer" do - with_fake_app do - invoke_then_revoke! Suspenders::JsonGenerator - - expect("config/initializers/oj.rb").not_to exist_as_a_file - end - end - end -end diff --git a/spec/suspenders/generators/lint_generator_spec.rb b/spec/suspenders/generators/lint_generator_spec.rb deleted file mode 100644 index a7f983ce5..000000000 --- a/spec/suspenders/generators/lint_generator_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::LintGenerator, type: :generator do - describe "invoke" do - it "bundles the standardrb gem" do - with_fake_app do - invoke! Suspenders::LintGenerator - - expect("Gemfile") - .to match_contents(/gem .standard./) - .and have_no_syntax_error - end - end - - it "adds the standardrb rake tasks to rake" do - with_fake_app do - invoke! Suspenders::LintGenerator - - # standardrb is a Suspenders dependency, so the require of the - # rake task works and we don't need to fake it - rake_output = `rake -T` - - expect(rake_output.lines.size).to eq 3 - expect(rake_output.lines[0]).to start_with("rake standard") - expect(rake_output.lines[1]).to start_with("rake standard:fix") - expect(rake_output.lines[2]).to start_with("rake standard:fix_unsafely") - end - end - end - - describe "revoke" do - it "removes the standardrb gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::LintGenerator - - expect("Gemfile") - .to not_match_contents(/gem .standard./) - .and have_no_syntax_error - end - end - - it "removes the standardrb rake tasks from rake" do - with_fake_app do - invoke_then_revoke! Suspenders::LintGenerator - - expect(`rake -T`).to be_empty - end - end - end -end diff --git a/spec/suspenders/generators/production/compression_generator_spec.rb b/spec/suspenders/generators/production/compression_generator_spec.rb deleted file mode 100644 index 8c3ef96b7..000000000 --- a/spec/suspenders/generators/production/compression_generator_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Production::CompressionGenerator, type: :generator do - describe "invoke" do - it "adds Rack::Deflater to the middleware" do - with_fake_app do - invoke! Suspenders::Production::CompressionGenerator - - expect("config/environments/production.rb") - .to match_contents(%r{config.middleware.use Rack::Deflater}) - end - end - end - - describe "revoke" do - it "removes Rack::Deflater from the middleware" do - with_fake_app do - invoke_then_revoke! Suspenders::Production::CompressionGenerator - - expect("config/environments/production.rb") - .not_to match_contents(%r{Rack::Deflater}) - end - end - end -end diff --git a/spec/suspenders/generators/production/deployment_generator_spec.rb b/spec/suspenders/generators/production/deployment_generator_spec.rb deleted file mode 100644 index d74e7101e..000000000 --- a/spec/suspenders/generators/production/deployment_generator_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Production::DeploymentGenerator, type: :generator do - def copy_files_to_fake_app - copy_file "README.md.erb", "README.md" - end - - describe "invoke" do - it "generates a bin/deploy binary" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::Production::DeploymentGenerator - - expect("bin/deploy").to exist_as_a_file.and be_executable - end - end - - it "generates a README entry" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::Production::DeploymentGenerator - - expect("README.md").to match_contents(%r{bin/deploy}) - end - end - end - - describe "revoke" do - it "destroys the bin/deploy binary" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::Production::DeploymentGenerator - - expect("bin/deploy").not_to exist_as_a_file - end - end - - it "destroys the README entry" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::Production::DeploymentGenerator - - expect("README.md").not_to match_contents(%r{bin/deploy}) - end - end - end -end diff --git a/spec/suspenders/generators/production/email_generator_spec.rb b/spec/suspenders/generators/production/email_generator_spec.rb deleted file mode 100644 index b9b312069..000000000 --- a/spec/suspenders/generators/production/email_generator_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Production::EmailGenerator, type: :generator do - describe "invoke" do - it "generates the config/smtp.rb file" do - with_fake_app do - invoke! Suspenders::Production::EmailGenerator - - expect("config/smtp.rb").to match_contents(%r{SMTP_SETTINGS\s*=}) - end - end - - it "adds smtp configuration to production.rb" do - with_fake_app do - invoke! Suspenders::Production::EmailGenerator - - contents = read_file("config/environments/production.rb") - - expect(contents) - .to start_with(%(require Rails.root.join("config/smtp")\n\n)) - - expect(contents.lines) - .to include(" config.action_mailer.delivery_method = :smtp\n") - .and include(" config.action_mailer.smtp_settings = SMTP_SETTINGS\n") - end - end - - it "adds smtp env configuration to app.json" do - with_fake_app do - invoke! Suspenders::Production::EmailGenerator - - expect("app.json").to contain_json( - env: { - SMTP_ADDRESS: {required: true}, - SMTP_DOMAIN: {required: true}, - SMTP_PASSWORD: {required: true}, - SMTP_USERNAME: {required: true} - } - ) - end - end - end - - describe "revoke" do - it "destroys the config/smtp.rb file" do - with_fake_app do - invoke_then_revoke! Suspenders::Production::EmailGenerator - - expect("config/smtp.rb").not_to exist_as_a_file - end - end - - it "removes smtp configuration from config/smtp.rb" do - with_fake_app do - invoke_then_revoke! Suspenders::Production::EmailGenerator - - expect("config/environments/production.rb") - .to not_match_contents(%r{require.+config/smtp}) - .and not_match_contents(%r{action_mailer.delivery_method\s*=\s*:smtp}) - .and not_match_contents(%r{action_mailer.smtp_settings\s*=\s*SMTP_SETTINGS}) - end - end - - it "removes smtp env configuration from app.json" do - with_fake_app do - invoke_then_revoke! Suspenders::Production::EmailGenerator - - expect("app.json").not_to contain_json( - env: { - SMTP_ADDRESS: {required: true}, - SMTP_DOMAIN: {required: true}, - SMTP_PASSWORD: {required: true}, - SMTP_USERNAME: {required: true} - } - ) - end - end - end -end diff --git a/spec/suspenders/generators/production/manifest_generator_spec.rb b/spec/suspenders/generators/production/manifest_generator_spec.rb deleted file mode 100644 index 223f29a2d..000000000 --- a/spec/suspenders/generators/production/manifest_generator_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Production::ManifestGenerator, type: :generator do - def setup_rails_stub(app_class_name: nil) - RailsStub.stub_app_class(app_class_name: app_class_name) - end - - describe "invoke" do - it "generates the manifest for a production build" do - with_fake_app do - setup_rails_stub app_class_name: "SomeApp::Application" - - invoke! Suspenders::Production::ManifestGenerator - - expect("app.json").to contain_json( - name: "some-app", - env: { - APPLICATION_HOST: {required: true}, - AUTO_MIGRATE_DB: {value: true}, - EMAIL_RECIPIENTS: {required: true}, - HEROKU_APP_NAME: {required: true}, - HEROKU_PARENT_APP_NAME: {required: true}, - RACK_ENV: {required: true}, - SECRET_KEY_BASE: {generator: "secret"} - } - ) - end - end - end - - describe "revoke" do - it "destroys the manifest for a production build" do - with_fake_app do - setup_rails_stub app_class_name: "SomeApp::Application" - - invoke_then_revoke! Suspenders::Production::ManifestGenerator - - expect("app.json").not_to contain_json( - name: "some-app", - env: { - APPLICATION_HOST: {required: true}, - AUTO_MIGRATE_DB: {value: true}, - EMAIL_RECIPIENTS: {required: true}, - HEROKU_APP_NAME: {required: true}, - HEROKU_PARENT_APP_NAME: {required: true}, - RACK_ENV: {required: true}, - SECRET_KEY_BASE: {generator: "secret"} - } - ) - end - end - end -end diff --git a/spec/suspenders/generators/production/single_redirect_spec.rb b/spec/suspenders/generators/production/single_redirect_spec.rb deleted file mode 100644 index 99b68baa0..000000000 --- a/spec/suspenders/generators/production/single_redirect_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Production::SingleRedirect, type: :generator do - describe "invoke" do - it "adds Rack::CanonicalHost to the production middleware" do - with_fake_app do - invoke! Suspenders::Production::SingleRedirect - - middleware_canonical_host = - "config.middleware.use Rack::CanonicalHost, " \ - 'ENV.fetch("APPLICATION_HOST")' - - expect("config/environments/production.rb") - .to match_contents(/#{Regexp.escape(middleware_canonical_host)}/) - end - end - end - - describe "revoke" do - it "removes Rack::CanonicalHost from the production middleware" do - with_fake_app do - invoke_then_revoke! Suspenders::Production::SingleRedirect - - middleware_canonical_host = - "config.middleware.use Rack::CanonicalHost, " \ - 'ENV.fetch("APPLICATION_HOST")' - - expect("config/environments/production.rb") - .not_to match_contents(/#{Regexp.escape(middleware_canonical_host)}/) - end - end - end -end diff --git a/spec/suspenders/generators/profiler_generator_spec.rb b/spec/suspenders/generators/profiler_generator_spec.rb deleted file mode 100644 index 93a97a93c..000000000 --- a/spec/suspenders/generators/profiler_generator_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::ProfilerGenerator, type: :generator do - def copy_files_to_fake_app - copy_file "README.md.erb", "README.md" - end - - describe "invoke" do - it "generates a rack-mini-profiler initializer" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::ProfilerGenerator - - expect("config/initializers/rack_mini_profiler.rb").to \ - match_contents(/Rack::MiniProfilerRails.initialize/) - end - end - - it "adds a rack-mini-profiler entry to the README" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::ProfilerGenerator - - expect("README.md") - .to match_contents(/Profiler/) - .and match_contents(/rack-mini-profiler/) - end - end - - it "bundles the rack-mini-profiler gem" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::ProfilerGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(/rack-mini-profiler/) - end - end - - it "adds rack-mini-profiler env variables to .sample.env" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::ProfilerGenerator - - expect(".sample.env").to match_contents(/RACK_MINI_PROFILER=0/) - end - end - end - - describe "revoke" do - it "destroys the rack-mini-profiler initializer" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::ProfilerGenerator - - expect("config/initializers/rack_mini_profiler.rb").not_to exist_as_a_file - end - end - - it "removes the rack-mini-profiler entry from the README" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::ProfilerGenerator - - expect("README.md") - .to not_match_contents(/Profiler/) - .and not_match_contents(/rack-mini-profiler/) - end - end - - it "removes the rack-mini-profiler gem" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::ProfilerGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "removes the rack-mini-profiler env variables" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::ProfilerGenerator - - expect(".sample.env").not_to match_contents(/RACK_MINI_PROFILER=0/) - end - end - end -end diff --git a/spec/suspenders/generators/runner_generator_spec.rb b/spec/suspenders/generators/runner_generator_spec.rb deleted file mode 100644 index a537f7b39..000000000 --- a/spec/suspenders/generators/runner_generator_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::RunnerGenerator, type: :generator do - def copy_files_to_fake_app - copy_file "bin_setup", "bin/setup" - copy_file "README.md.erb", "README.md" - end - - describe "invoke" do - it "creates a Procfile" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::RunnerGenerator - - expect("Procfile").to exist_as_a_file - end - end - - it "creates a .sample.env file" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::RunnerGenerator - - expect(".sample.env").to exist_as_a_file - end - end - - it "adds .sample.env handling to bin/setup" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::RunnerGenerator - - expect("bin/setup").to match_contents(/\.sample\.env/) - end - end - - it "adds .sample.env information to the README" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::RunnerGenerator - - expect("README.md").to match_contents(/\.sample\.env/) - end - end - end - - describe "revoke" do - it "destroys Procfile" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::RunnerGenerator - - expect("Procfile").not_to exist_as_a_file - end - end - - it "destroys .sample.env" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::RunnerGenerator - - expect(".sample.env").not_to exist_as_a_file - end - end - - it "removes .sample.env handling from bin/setup" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::RunnerGenerator - - expect("bin/setup").not_to match_contents(/\.sample\.env/) - end - end - - it "removes .sample.env information from the README" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::RunnerGenerator - - expect("README.md").not_to match_contents(/\.sample\.env/) - end - end - end -end diff --git a/spec/suspenders/generators/staging/pull_requests_generator_spec.rb b/spec/suspenders/generators/staging/pull_requests_generator_spec.rb deleted file mode 100644 index 25921389b..000000000 --- a/spec/suspenders/generators/staging/pull_requests_generator_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::Staging::PullRequestsGenerator, type: :generator do - def setup_rails_stub(app_class_name: nil) - RailsStub.stub_app_class(app_class_name: app_class_name) - end - - describe "invoke" do - it "configures production.rb for heroku" do - with_fake_app do - setup_rails_stub - - invoke! Suspenders::Staging::PullRequestsGenerator - - expect(read_file("config/environments/production.rb")).to include( - [ - "", - ' if ENV.fetch("HEROKU_APP_NAME", "").include?("staging-pr-")', - ' ENV["APPLICATION_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com"', - ' ENV["ASSET_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com"', - " end" - ].join("\n") - ) - end - end - - it "adds heroku to bin/setup_review_app with the correct app name" do - with_fake_app do - setup_rails_stub app_class_name: "SomeFakeApp::Application" - - invoke! Suspenders::Staging::PullRequestsGenerator - - expect("bin/setup_review_app") - .to match_contents(%r{APP_NAME=some-fake-app-staging-pr-\$1}) - end - end - end - - describe "revoke" do - it "removes heroku from production.rb" do - with_fake_app do - setup_rails_stub app_class_name: "SomeFakeApp::Application" - - invoke_then_revoke! Suspenders::Staging::PullRequestsGenerator - - expect("config/environments/production.rb") - .not_to match_contents(%r{APP_NAME=some-fake-app-staging-pr-\$1}) - end - end - - it "removes heroku from bin/setup_review_app" do - with_fake_app do - setup_rails_stub - - invoke_then_revoke! Suspenders::Staging::PullRequestsGenerator - - expect("bin/setup_review_app").not_to exist_as_a_file - end - end - end -end diff --git a/spec/suspenders/generators/static_generator_spec.rb b/spec/suspenders/generators/static_generator_spec.rb deleted file mode 100644 index 058701760..000000000 --- a/spec/suspenders/generators/static_generator_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::StaticGenerator, type: :generator do - describe "invoke" do - it "bundles the high_voltage gem" do - with_fake_app do - invoke! Suspenders::StaticGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and have_bundled("install") - .matching(/high_voltage/) - end - end - - it "creates a views/pages/.keep file" do - with_fake_app do - invoke! Suspenders::StaticGenerator - - expect("app/views/pages/.keep").to exist_as_a_file - end - end - end - - describe "revoke" do - it "removes the high_voltage gem from Gemfile" do - with_fake_app do - invoke_then_revoke! Suspenders::StaticGenerator - - expect("Gemfile") - .to have_no_syntax_error - .and match_original_file - .and not_have_bundled - end - end - - it "deletes the views/pages/.keep file" do - with_fake_app do - invoke_then_revoke! Suspenders::StaticGenerator - - expect("app/views/pages/.keep").not_to exist_as_a_file - end - end - end -end diff --git a/spec/suspenders/generators/stylelint_generator_spec.rb b/spec/suspenders/generators/stylelint_generator_spec.rb deleted file mode 100644 index dc68e4584..000000000 --- a/spec/suspenders/generators/stylelint_generator_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -require "spec_helper" - -RSpec.describe Suspenders::StylelintGenerator, type: :generator do - def copy_files_to_fake_app - copy_file "hound.yml", ".hound.yml" - end - - describe "invoke" do - it "creates .stylelintrc.json" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::StylelintGenerator - - expect(".stylelintrc.json") - .to match_contents(%r{"extends": "@thoughtbot/stylelint-config"}) - end - end - - it "calls the lint generator" do - with_fake_app do - copy_files_to_fake_app - - expect(Suspenders::LintGenerator) - .to receive(:dispatch) - .with(nil, [], [], hash_including(behavior: :invoke)) - - invoke! Suspenders::StylelintGenerator - end - end - - it "adds stylelint and @thoughtbot/stylelint-config to package.json" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::StylelintGenerator - - expect("package.json") - .to have_yarned("add stylelint @thoughtbot/stylelint-config --dev") - end - end - - it "uncomments the hound config_file option" do - with_fake_app do - copy_files_to_fake_app - - invoke! Suspenders::StylelintGenerator - - expect(".hound.yml").to( - match_contents(/^ config_file: \.stylelintrc\.json/) - ) - end - end - end - - context "revoke" do - it "removes .stylelintrc.json" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::StylelintGenerator - - expect(".stylelintrc.json").not_to exist_as_a_file - end - end - - it "removes stylelint and @thoughtbot/stylelint-config from package.json" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::StylelintGenerator - - expect("package.json") - .to have_yarned("remove stylelint @thoughtbot/stylelint-config") - end - end - - it "comments in the hound config_file option" do - with_fake_app do - copy_files_to_fake_app - - invoke_then_revoke! Suspenders::StylelintGenerator - - expect(".hound.yml") - .to match_contents(/^ # config_file: \.stylelintrc\.json/) - end - end - end -end diff --git a/suspenders.gemspec b/suspenders.gemspec index 872ec8fe0..60cf34a72 100644 --- a/suspenders.gemspec +++ b/suspenders.gemspec @@ -1,37 +1,31 @@ -$:.push File.expand_path("../lib", __FILE__) -require "suspenders/version" -require "date" +require_relative "lib/suspenders/version" -Gem::Specification.new do |s| - minimum_ruby_version, maximum_ruby_version = Suspenders::RUBY_VERSION_RANGE +Gem::Specification.new do |spec| + spec.name = "suspenders" + spec.version = Suspenders::VERSION + spec.required_ruby_version = Suspenders::MINIMUM_RUBY_VERSION + spec.authors = ["thoughtbot"] + spec.email = ["support@thoughtbot.com"] + spec.homepage = "http://github.com/thoughtbot/suspenders" + spec.summary = "Rails generators using thoughtbot's best practices." + spec.description = <<~HERE + Suspenders is a Rails plugin containing generators for configuring Rails + applications. It is used by thoughtbot to get a jump start on a new or + existing app. Use Suspenders if you're in a rush to build something amazing; + don't use it if you like missing deadlines. + HERE - s.required_ruby_version = [">= #{minimum_ruby_version}", "<= #{maximum_ruby_version}"] - s.required_rubygems_version = ">= 3.0.0" - s.authors = ["thoughtbot"] + spec.license = "MIT" - s.description = <<~HERE - Suspenders is a base Rails project that you can upgrade. It is used by - thoughtbot to get a jump start on a working app. Use Suspenders if you're in a - rush to build something amazing; don't use it if you like missing deadlines. - HERE + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = "https://github.com/thoughtbot/suspenders/blob/main/NEWS.md" - s.email = "support@thoughtbot.com" - s.executables = ["suspenders"] - s.extra_rdoc_files = %w[README.md LICENSE] - s.files = Dir[".ruby-version", "bin/suspenders", "{docs,lib,templates}/**/*", "LICENSE", "*.md"] - s.homepage = "http://github.com/thoughtbot/suspenders" - s.license = "MIT" - s.name = "suspenders" - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.summary = "Generate a Rails app using thoughtbot's best practices." - s.version = Suspenders::VERSION + spec.files = Dir.chdir(File.expand_path(__dir__)) do + Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] + end - s.add_dependency "parser", ">= 3.0" - s.add_dependency "bundler", ">= 2.1" - s.add_dependency "rails", Suspenders::RAILS_VERSION + spec.add_dependency "rails", Suspenders::RAILS_VERSION - s.add_development_dependency "pry" - s.add_development_dependency "rspec", "~> 3.2" - s.add_development_dependency "standard" + spec.add_development_dependency "standard" end diff --git a/templates/Gemfile.erb b/templates/Gemfile.erb deleted file mode 100644 index 5e37df070..000000000 --- a/templates/Gemfile.erb +++ /dev/null @@ -1,48 +0,0 @@ -source "https://rubygems.org" - -git_source(:github) do |repo_name| - repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") - "https://github.com/#{repo_name}.git" -end - -ruby <%= RUBY_VERSION.inspect %> - -<% if options[:api] %> -gem "sprockets", "< 4" -<% end %> - -gem "bootsnap", require: false -gem "cssbundling-rails" -gem "honeybadger" -gem "jsbundling-rails" -gem "pg" -gem "puma" -gem "rack-canonical-host" -gem "rails", "<%= Suspenders::RAILS_VERSION %>" -gem "recipient_interceptor" -gem "sassc-rails" -gem "skylight" -gem "sprockets-rails" -gem "stimulus-rails" -gem "title" -gem "turbo-rails" -gem "tzinfo-data", platforms: [:mingw, :x64_mingw, :mswin, :jruby] - -group :development do - gem "listen" - gem "web-console" -end - -group :development, :test do - gem "awesome_print" - gem "pry-byebug" - gem "pry-rails" -end - -group :test do - gem "formulaic" - gem "launchy" - gem "webmock" -end - -gem "suspenders", group: [:development, :test] diff --git a/templates/Procfile b/templates/Procfile deleted file mode 100644 index e63b75326..000000000 --- a/templates/Procfile +++ /dev/null @@ -1,2 +0,0 @@ -web: bundle exec puma -p $PORT -C ./config/puma.rb -worker: bundle exec sidekiq diff --git a/templates/README.md.erb b/templates/README.md.erb deleted file mode 100644 index 41347ec45..000000000 --- a/templates/README.md.erb +++ /dev/null @@ -1,28 +0,0 @@ -# <%= app_name.humanize %> - -## Getting Started - -After you have cloned this repo, run this setup script to set up your machine -with the necessary dependencies to run and test this app: - - % ./bin/setup - -It assumes you have a machine equipped with Ruby, Postgres, etc. If not, set up -your machine with [this script]. - -[this script]: https://github.com/thoughtbot/laptop - -After setting up, you can run the application using [Heroku Local]: - - % heroku local - -[Heroku Local]: https://devcenter.heroku.com/articles/heroku-local - -## Guidelines - -Use the following guides for getting things done, programming well, and -programming in style. - -* [Protocol](http://github.com/thoughtbot/guides/blob/master/protocol) -* [Best Practices](http://github.com/thoughtbot/guides/blob/master/best-practices) -* [Style](http://github.com/thoughtbot/guides/blob/master/style) diff --git a/templates/_analytics.html.erb b/templates/_analytics.html.erb deleted file mode 100644 index 98f13b184..000000000 --- a/templates/_analytics.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -<% if ENV["SEGMENT_KEY"] %> - -<% end %> diff --git a/templates/_css_overrides.html.erb b/templates/_css_overrides.html.erb deleted file mode 100644 index 1d7edcb73..000000000 --- a/templates/_css_overrides.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% if Rails.env.test? %> - -<% end %> diff --git a/templates/_flashes.html.erb b/templates/_flashes.html.erb deleted file mode 100644 index 084905881..000000000 --- a/templates/_flashes.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% if flash.any? %> -
- <% user_facing_flashes.each do |key, value| -%> -
<%= value %>
- <% end -%> -
-<% end %> diff --git a/templates/action_mailer.rb b/templates/action_mailer.rb deleted file mode 100644 index b9563a3bc..000000000 --- a/templates/action_mailer.rb +++ /dev/null @@ -1,5 +0,0 @@ -RSpec.configure do |config| - config.before(:each) do - ActionMailer::Base.deliveries.clear - end -end diff --git a/templates/active_job.rb b/templates/active_job.rb deleted file mode 100644 index ce7cbd7c2..000000000 --- a/templates/active_job.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "active_job/logging" -require "active_job/log_subscriber" - -ActiveSupport::Notifications.unsubscribe("enqueue.active_job") - -module ActiveJob - module Logging - class EnqueueLogSubscriber < LogSubscriber - define_method :enqueue, instance_method(:enqueue) - end - end -end - -ActiveJob::Logging::EnqueueLogSubscriber.attach_to(:active_job) diff --git a/templates/application.postcss.css b/templates/application.postcss.css deleted file mode 100644 index 9a2fbc1f5..000000000 --- a/templates/application.postcss.css +++ /dev/null @@ -1 +0,0 @@ -@import "normalize.css" diff --git a/templates/bin_auto_migrate b/templates/bin_auto_migrate deleted file mode 100755 index 84739b32a..000000000 --- a/templates/bin_auto_migrate +++ /dev/null @@ -1,5 +0,0 @@ - set -e - - if [ -n "$AUTO_MIGRATE_DB" ]; then - bundle exec rake db:migrate - fi diff --git a/templates/bin_deploy b/templates/bin_deploy deleted file mode 100755 index 9aa1b41b1..000000000 --- a/templates/bin_deploy +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# Run this script to deploy the app to Heroku. - -set -e - -branch="$(git symbolic-ref HEAD --short)" -target="${1:-staging}" - -git push "$target" "$branch:master" diff --git a/templates/bin_setup b/templates/bin_setup deleted file mode 100644 index 17f90bb0f..000000000 --- a/templates/bin_setup +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# Set up Rails app. Run this script immediately after cloning the codebase. -# https://github.com/thoughtbot/guides/tree/master/protocol - -# Exit if any subcommand fails -set -e - -# Set up Ruby dependencies via Bundler -gem install bundler --conservative -bundle check || bundle install - -# Install JavaScript dependencies -bin/yarn - -# Set up database and add any development seed data -bin/rails dev:prime - -if [ ! -d .git/safe ] && echo $PATH | grep .git/safe > /dev/null; then - echo "-----------------------------------------------------------------------" - echo - echo "-> When you trust this repo, remember to run: mkdir -p .git/safe" - echo -fi - -# Only if this isn't CI -if [ -z "$CI" ]; then -fi diff --git a/templates/bin_setup_review_app.erb b/templates/bin_setup_review_app.erb deleted file mode 100644 index 1f23f93b9..000000000 --- a/templates/bin_setup_review_app.erb +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Run this script to set up a review app's database and worker dyno - -set -e - -if [ -z "$1" ]; then - printf "You must provide a review app (same as the pull request) id.\n" - exit 64 -fi - -PARENT_APP_NAME=<%= app_name.dasherize %>-staging -APP_NAME=<%= app_name.dasherize %>-staging-pr-$1 - -heroku pg:backups:capture --app $PARENT_APP_NAME - -URL=`heroku pg:backups public-url --app $PARENT_APP_NAME` - -heroku pg:backups restore $URL DATABASE_URL --confirm $APP_NAME --app $APP_NAME -heroku ps:scale worker=1 --app $APP_NAME -heroku restart --app $APP_NAME diff --git a/templates/bin_yarn b/templates/bin_yarn deleted file mode 100755 index c42ebc61e..000000000 --- a/templates/bin_yarn +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir(APP_ROOT) do - yarn = ENV["PATH"].split(File::PATH_SEPARATOR) - .select { |dir| File.expand_path(dir) != __dir__ } - .product(["yarn", "yarnpkg", "yarn.cmd", "yarn.ps1"]) - .map { |dir, file| File.expand_path(file, dir) } - .find { |file| File.executable?(file) } - - if yarn - exec yarn, *ARGV - else - warn "Yarn executable was not detected in the system." - warn "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end -end diff --git a/templates/bundler_audit.rake b/templates/bundler_audit.rake deleted file mode 100644 index 72f6b5120..000000000 --- a/templates/bundler_audit.rake +++ /dev/null @@ -1,4 +0,0 @@ -if Rails.env.development? || Rails.env.test? - require "bundler/audit/task" - Bundler::Audit::Task.new -end diff --git a/templates/chromedriver.rb b/templates/chromedriver.rb deleted file mode 100644 index 4091d1531..000000000 --- a/templates/chromedriver.rb +++ /dev/null @@ -1,27 +0,0 @@ -require "selenium/webdriver" - -Capybara.register_driver :chrome do |app| - Capybara::Selenium::Driver.new(app, browser: :chrome) -end - -Capybara.register_driver :headless_chrome do |app| - options = ::Selenium::WebDriver::Chrome::Options.new - options.headless! - options.add_argument "--window-size=1680,1050" - - Capybara::Selenium::Driver.new app, - browser: :chrome, - options: options -end - -Capybara.javascript_driver = :headless_chrome - -RSpec.configure do |config| - config.before(:each, type: :system) do - driven_by :rack_test - end - - config.before(:each, type: :system, js: true) do - driven_by Capybara.javascript_driver - end -end diff --git a/templates/circle.yml.erb b/templates/circle.yml.erb deleted file mode 100644 index 2d25fe186..000000000 --- a/templates/circle.yml.erb +++ /dev/null @@ -1,6 +0,0 @@ -database: - override: - - RAILS_ENV=development bin/setup -test: - override: - - COVERAGE=true bin/rake diff --git a/templates/config_locales_en.yml.erb b/templates/config_locales_en.yml.erb deleted file mode 100644 index f7af541a6..000000000 --- a/templates/config_locales_en.yml.erb +++ /dev/null @@ -1,19 +0,0 @@ -en: - date: - formats: - default: - "%m/%d/%Y" - with_weekday: - "%a %m/%d/%y" - - time: - formats: - default: - "%a, %b %-d, %Y at %r" - date: - "%b %-d, %Y" - short: - "%B %d" - - titles: - application: <%= app_name.humanize %> diff --git a/templates/descriptions/advisories.md b/templates/descriptions/advisories.md deleted file mode 100644 index 2db4064e5..000000000 --- a/templates/descriptions/advisories.md +++ /dev/null @@ -1,5 +0,0 @@ -Show security advisories during development. - -Uses the `bundler-audit` gem and rake task to update the local security -database and show any relevant issues with the app's dependencies. This happens -on every test run and interaction with `bin/rake` and `bin/rails`. diff --git a/templates/descriptions/analytics.md b/templates/descriptions/analytics.md deleted file mode 100644 index 56f95dd95..000000000 --- a/templates/descriptions/analytics.md +++ /dev/null @@ -1,4 +0,0 @@ -Work with a user analytics service. - -Add the JavaScript for connecting to Segment to a partial and, if possible, -include that partial on every page. diff --git a/templates/descriptions/ci.md b/templates/descriptions/ci.md deleted file mode 100644 index 1d79105be..000000000 --- a/templates/descriptions/ci.md +++ /dev/null @@ -1,4 +0,0 @@ -Prepare the app for running tests on a continuous integration service. - -Sets up a CircleCI configuration using `bin/setup` to initialize the app and -`rake` to run the tests. Use SimpleCov for code coverage metrics on CI. diff --git a/templates/descriptions/compression.md b/templates/descriptions/compression.md deleted file mode 100644 index f4142ac4b..000000000 --- a/templates/descriptions/compression.md +++ /dev/null @@ -1,4 +0,0 @@ -Compress HTTP requests at the Rails layer. - -This uses `Rack::Deflater`, and is done at the app layer instead of at the Web -server layer. diff --git a/templates/descriptions/db_optimizations.md b/templates/descriptions/db_optimizations.md deleted file mode 100644 index c89f2bc4f..000000000 --- a/templates/descriptions/db_optimizations.md +++ /dev/null @@ -1,2 +0,0 @@ -Get database performance insights as you develop. This installs and configures -Bullet. diff --git a/templates/descriptions/deployment.md b/templates/descriptions/deployment.md deleted file mode 100644 index 114fd345d..000000000 --- a/templates/descriptions/deployment.md +++ /dev/null @@ -1,5 +0,0 @@ -Script and document the deployment. - -This adds a `bin/deploy` script, to be called like `deploy staging` or -`deploy production`, along with updates to the README.md describing how to use -it. diff --git a/templates/descriptions/email.md b/templates/descriptions/email.md deleted file mode 100644 index a353aa5c9..000000000 --- a/templates/descriptions/email.md +++ /dev/null @@ -1,9 +0,0 @@ -Configure the app for email. - -Set the app up with SMTP in production. This expects the following environment -variables to be set: - -- `SMTP_ADDRESS` -- `SMTP_DOMAIN` -- `SMTP_PASSWORD` -- `SMTP_USERNAME` diff --git a/templates/descriptions/factories.md b/templates/descriptions/factories.md deleted file mode 100644 index e9dcedb11..000000000 --- a/templates/descriptions/factories.md +++ /dev/null @@ -1,12 +0,0 @@ -Build test data with clarity and ease. - -This uses FactoryBot to help you define dummy and test data for your test -suite. The `create`, `build`, and `build_stubbed` class methods are directly -available to all tests. - -We recommend putting FactoryBot definitions in one `spec/factories.rb` file, at -least until it grows unwieldy. This helps reduce confusion around circular -dependencies and makes it easy to jump between definitions. - -Outside of the tests, the `dev:prime` rake task can be used to insert initial -development data into the database. You can use FactoryBot here, too. diff --git a/templates/descriptions/force_tls.md b/templates/descriptions/force_tls.md deleted file mode 100644 index 7f80d3209..000000000 --- a/templates/descriptions/force_tls.md +++ /dev/null @@ -1 +0,0 @@ -Redirect users to the HTTPS URL on the production Web site. diff --git a/templates/descriptions/forms.md b/templates/descriptions/forms.md deleted file mode 100644 index 28fb1997a..000000000 --- a/templates/descriptions/forms.md +++ /dev/null @@ -1 +0,0 @@ -Make forms easier to make with form helpers. This mostly involves SimpleForm. diff --git a/templates/descriptions/inline_svg.md b/templates/descriptions/inline_svg.md deleted file mode 100644 index 36a49e3f0..000000000 --- a/templates/descriptions/inline_svg.md +++ /dev/null @@ -1,2 +0,0 @@ -Render SVG images inline, as a potential performance improvement for the -viewer. diff --git a/templates/descriptions/jobs.md b/templates/descriptions/jobs.md deleted file mode 100644 index 32aea6eea..000000000 --- a/templates/descriptions/jobs.md +++ /dev/null @@ -1,3 +0,0 @@ -Set up our favorite job runner. - -Currently we like Sidekiq. Run all tests inline by default. diff --git a/templates/descriptions/js_driver.md b/templates/descriptions/js_driver.md deleted file mode 100644 index 49a853ee7..000000000 --- a/templates/descriptions/js_driver.md +++ /dev/null @@ -1,4 +0,0 @@ -Set up the test suite for running JavaScript tests. - -This uses the latest and greatest JavaScript test runner -- currently, -chromedriver. It comes with a headless mode and a headful/debugging mode. diff --git a/templates/descriptions/json.md b/templates/descriptions/json.md deleted file mode 100644 index 82f6c3a31..000000000 --- a/templates/descriptions/json.md +++ /dev/null @@ -1 +0,0 @@ -Use the fastest JSON parser available. diff --git a/templates/descriptions/lint.md b/templates/descriptions/lint.md deleted file mode 100644 index e0cc7939e..000000000 --- a/templates/descriptions/lint.md +++ /dev/null @@ -1,3 +0,0 @@ -Prepare the app for style linting. - -This sets up your app to use Hound with a default Hound configuration. diff --git a/templates/descriptions/manifest.md b/templates/descriptions/manifest.md deleted file mode 100644 index 290b554ee..000000000 --- a/templates/descriptions/manifest.md +++ /dev/null @@ -1,2 +0,0 @@ -Write the AppManifest (`app.json`) document with all the environment variables -we require. diff --git a/templates/descriptions/profiler.md b/templates/descriptions/profiler.md deleted file mode 100644 index 9f5a927d2..000000000 --- a/templates/descriptions/profiler.md +++ /dev/null @@ -1,7 +0,0 @@ -Show runtime profiling for your Rails app as you develop it. - -This uses the `rack-mini-profiler` gem to show a speed badge on every page. -This is controlled by the `RACK_MINI_PROFILER` environment variable which -defaults to `0` in the `.sample.env`. Set it to `1` to enable profiling. - -Updates your README.md to explain this environment variable. diff --git a/templates/descriptions/pull_requests.md b/templates/descriptions/pull_requests.md deleted file mode 100644 index c7433c84b..000000000 --- a/templates/descriptions/pull_requests.md +++ /dev/null @@ -1,4 +0,0 @@ -Create a staging environment for each pull request. - -This glues Heroku review apps to GitHub pull requests, populating the database -from the generic staging environment on a low-scale review app. diff --git a/templates/descriptions/runner.md b/templates/descriptions/runner.md deleted file mode 100644 index 3af72d869..000000000 --- a/templates/descriptions/runner.md +++ /dev/null @@ -1,10 +0,0 @@ -Set up the app to run locally with ease. - -Use Puma and Sidekiq to run the app. This can be done via either -`heroku local` or any Foreman-compatible project runner (e.g. `foreman start`). - -Configure your app using `.env`. Installs a basic `.sample.env` that is meant -to be checked into git and used as a template for your `.env`. The `bin/setup` -script is modified to safely copy `.sample.env` to `.env` for you. - -Document all of this in the README. diff --git a/templates/descriptions/single_redirect.md b/templates/descriptions/single_redirect.md deleted file mode 100644 index ea7947089..000000000 --- a/templates/descriptions/single_redirect.md +++ /dev/null @@ -1 +0,0 @@ -Canonicalize the URL by configuring the `Rack::CanonicalHost` middleware. diff --git a/templates/descriptions/static.md b/templates/descriptions/static.md deleted file mode 100644 index c09ac4aab..000000000 --- a/templates/descriptions/static.md +++ /dev/null @@ -1,5 +0,0 @@ -Easily add static pages to your dynamic Rails app. - -Files placed in the `app/views/pages` directory are rendered using the standard -Rails view renderer and accessible at `/pages/:view_name`, via the -`high_voltage` gem. diff --git a/templates/descriptions/stylelint.md b/templates/descriptions/stylelint.md deleted file mode 100644 index 71e06ac4d..000000000 --- a/templates/descriptions/stylelint.md +++ /dev/null @@ -1,3 +0,0 @@ -Enable stylesheet linting. - -This configures the stylelint tool to work locally and integrated with Hound. diff --git a/templates/descriptions/stylesheet_base.md b/templates/descriptions/stylesheet_base.md deleted file mode 100644 index cc03bee29..000000000 --- a/templates/descriptions/stylesheet_base.md +++ /dev/null @@ -1 +0,0 @@ -Adds PostCSS Normalize diff --git a/templates/descriptions/testing.md b/templates/descriptions/testing.md deleted file mode 100644 index 04a389372..000000000 --- a/templates/descriptions/testing.md +++ /dev/null @@ -1,9 +0,0 @@ -Set up the project for an in-depth test-driven development workflow. - -- Maintain the test DB schema. -- Clear mail deliveries between tests. -- Import i18n helpers for use in tests. -- Prepare for system tests in `spec/system`. -- Integrate Formulaic for easier form testing. -- RSpec infers the file type based on the directory name. -- Install and configure RSpec and shoulda-matchers. diff --git a/templates/descriptions/timeout.md b/templates/descriptions/timeout.md deleted file mode 100644 index 994870f57..000000000 --- a/templates/descriptions/timeout.md +++ /dev/null @@ -1,4 +0,0 @@ -Kill Rack requests that last too long. - -This adds the `rack-timeout` gem and configures it to kill the connection after -10 seconds. diff --git a/templates/descriptions/views.md b/templates/descriptions/views.md deleted file mode 100644 index 0d79eeaa4..000000000 --- a/templates/descriptions/views.md +++ /dev/null @@ -1,8 +0,0 @@ -View templates for flash, JavaScript, and CSS. - -- Disable CSS animations in tests. -- Run JavaScript when the page has loaded. -- Use the `title` gem for controlling the page title via i18n. -- Insert one-off JavaScript into a `:javascript` content block. -- Creates the directory for storing generic, application-level partials. -- Render user-facing partials (alert, error, notice, success) on all pages. diff --git a/templates/dev.rake b/templates/dev.rake deleted file mode 100644 index 7a94175f1..000000000 --- a/templates/dev.rake +++ /dev/null @@ -1,12 +0,0 @@ -if Rails.env.development? || Rails.env.test? - require "factory_bot" - - namespace :dev do - desc "Sample data for local development environment" - task prime: "db:setup" do - include FactoryBot::Syntax::Methods - - # create(:user, email: "user@example.com", password: "password") - end - end -end diff --git a/templates/email.rb b/templates/email.rb deleted file mode 100644 index 3ac581b04..000000000 --- a/templates/email.rb +++ /dev/null @@ -1,3 +0,0 @@ -if ENV["EMAIL_RECIPIENTS"].present? - Mail.register_interceptor RecipientInterceptor.new(ENV["EMAIL_RECIPIENTS"]) -end diff --git a/templates/errors.rb b/templates/errors.rb deleted file mode 100644 index 8b29cc6ac..000000000 --- a/templates/errors.rb +++ /dev/null @@ -1,35 +0,0 @@ -require "net/http" -require "net/smtp" - -# Example: -# begin -# some http call -# rescue *HTTP_ERRORS => error -# notify_hoptoad error -# end - -HTTP_ERRORS = [ - EOFError, - Errno::ECONNRESET, - Errno::EINVAL, - Errno::ECONNREFUSED, - Net::HTTPBadResponse, - Net::HTTPHeaderSyntaxError, - Net::ProtocolError, - Timeout::Error -] - -SMTP_SERVER_ERRORS = [ - IOError, - Net::SMTPAuthenticationError, - Net::SMTPServerBusy, - Net::SMTPUnknownError, - Timeout::Error -] - -SMTP_CLIENT_ERRORS = [ - Net::SMTPFatalError, - Net::SMTPSyntaxError -] - -SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS diff --git a/templates/factories.rb b/templates/factories.rb deleted file mode 100644 index 3bfcbd203..000000000 --- a/templates/factories.rb +++ /dev/null @@ -1,2 +0,0 @@ -FactoryBot.define do -end diff --git a/templates/factory_bot_rspec.rb b/templates/factory_bot_rspec.rb deleted file mode 100644 index 4943f172e..000000000 --- a/templates/factory_bot_rspec.rb +++ /dev/null @@ -1,5 +0,0 @@ -FactoryBot.use_parent_strategy = true - -RSpec.configure do |config| - config.include FactoryBot::Syntax::Methods -end diff --git a/templates/flashes_helper.rb b/templates/flashes_helper.rb deleted file mode 100644 index bef014fde..000000000 --- a/templates/flashes_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -module FlashesHelper - def user_facing_flashes - flash.to_hash.slice("alert", "error", "notice", "success") - end -end diff --git a/templates/hound.yml b/templates/hound.yml deleted file mode 100644 index 237ce19d3..000000000 --- a/templates/hound.yml +++ /dev/null @@ -1,15 +0,0 @@ -# See https://houndci.com/configuration for help. -haml: - # config_file: .haml-style.yml - enabled: true -javascript: - # config_file: .javascript-style.json - enabled: true - # ignore_file: .javascript_ignore -ruby: - enabled: false -scss: - enabled: false -stylelint: - # config_file: .stylelintrc.json - enabled: true diff --git a/templates/i18n.rb b/templates/i18n.rb deleted file mode 100644 index 0c61ce662..000000000 --- a/templates/i18n.rb +++ /dev/null @@ -1,3 +0,0 @@ -RSpec.configure do |config| - config.include ActionView::Helpers::TranslationHelper -end diff --git a/templates/inline_svg.rb b/templates/inline_svg.rb deleted file mode 100644 index d6cd050ae..000000000 --- a/templates/inline_svg.rb +++ /dev/null @@ -1,3 +0,0 @@ -InlineSvg.configure do |config| - config.raise_on_file_not_found = true -end diff --git a/templates/json_encoding.rb b/templates/json_encoding.rb deleted file mode 100644 index 292542fca..000000000 --- a/templates/json_encoding.rb +++ /dev/null @@ -1 +0,0 @@ -ActiveSupport::JSON::Encoding.time_precision = 0 diff --git a/templates/oj.rb b/templates/oj.rb deleted file mode 100644 index 6d888326f..000000000 --- a/templates/oj.rb +++ /dev/null @@ -1,3 +0,0 @@ -require "oj" - -Oj.optimize_rails diff --git a/templates/partials/ci_simplecov.rb b/templates/partials/ci_simplecov.rb deleted file mode 100644 index 985b11df8..000000000 --- a/templates/partials/ci_simplecov.rb +++ /dev/null @@ -1,14 +0,0 @@ -if ENV.fetch("COVERAGE", false) - require "simplecov" - - if ENV["CIRCLE_ARTIFACTS"] - dir = File.join(ENV["CIRCLE_ARTIFACTS"], "coverage") - SimpleCov.coverage_dir(dir) - end - - SimpleCov.start "rails" - - if defined?(Spring) && ENV["DISABLE_SPRING"].to_i == 1 - Rails.application.eager_load! - end -end diff --git a/templates/partials/db_optimizations_configuration.rb b/templates/partials/db_optimizations_configuration.rb deleted file mode 100644 index c2fdb35ad..000000000 --- a/templates/partials/db_optimizations_configuration.rb +++ /dev/null @@ -1,7 +0,0 @@ - - - config.after_initialize do - Bullet.enable = true - Bullet.bullet_logger = true - Bullet.rails_logger = true - end diff --git a/templates/partials/deployment_readme.md b/templates/partials/deployment_readme.md deleted file mode 100644 index 6c2b147ae..000000000 --- a/templates/partials/deployment_readme.md +++ /dev/null @@ -1,8 +0,0 @@ - -## Deploying - -If you have previously run the `./bin/setup` script, -you can deploy to staging and production with: - - % ./bin/deploy staging - % ./bin/deploy production diff --git a/templates/partials/email_smtp.rb b/templates/partials/email_smtp.rb deleted file mode 100644 index eae462ba7..000000000 --- a/templates/partials/email_smtp.rb +++ /dev/null @@ -1,2 +0,0 @@ - config.action_mailer.delivery_method = :smtp - config.action_mailer.smtp_settings = SMTP_SETTINGS diff --git a/templates/partials/profiler_readme.md b/templates/partials/profiler_readme.md deleted file mode 100644 index 2b5536470..000000000 --- a/templates/partials/profiler_readme.md +++ /dev/null @@ -1,8 +0,0 @@ - -## Profiler - -The [rack-mini-profiler] gem can be enabled by setting -`RACK_MINI_PROFILER=1` in the environment. This will display a speed -badge on every page. - -[rack-mini-profiler]: https://github.com/MiniProfiler/rack-mini-profiler diff --git a/templates/partials/pull_requests_config.rb b/templates/partials/pull_requests_config.rb deleted file mode 100644 index 0ae37b5ab..000000000 --- a/templates/partials/pull_requests_config.rb +++ /dev/null @@ -1,5 +0,0 @@ - if ENV.fetch("HEROKU_APP_NAME", "").include?("staging-pr-") - ENV["APPLICATION_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com" - ENV["ASSET_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com" - end - diff --git a/templates/partials/runner_readme.md b/templates/partials/runner_readme.md deleted file mode 100644 index 79b19db82..000000000 --- a/templates/partials/runner_readme.md +++ /dev/null @@ -1,31 +0,0 @@ -## Configuration - -Environment variables during local development are handled by the node-foreman -project runner. To provide environment variables, create a `.env` file at the -root of the project. In that file provide the environment variables listed in -`.sample.env`. The `bin/setup` script does this for you, but be careful about -overwriting your existing `.env` file. - -`app.json` also contains a list of environment variables that are required for -the application. The `.sample.env` file provides either non-secret vars that -can be copied directly into your own `.env` file or instructions on where to -obtain secret values. - -During development add any new environment variables needed by the application -to both `.sample.env` and `app.json`, providing either **public** default -values or brief instructions on where secret values may be found. - -Do not commit the `.env` file to the git repo. - -## Running the Application - -Use the `heroku local` runner to run the app locally as it would run on Heroku. -This uses the node-forman runner, which reads from the `Procfile` file. - -```sh -heroku local -``` - -Once the server is started the application is reachable at -`http://localhost:3000`. - diff --git a/templates/partials/runner_setup.rb b/templates/partials/runner_setup.rb deleted file mode 100644 index 071d24ce9..000000000 --- a/templates/partials/runner_setup.rb +++ /dev/null @@ -1,2 +0,0 @@ -puts "\n== Copying sample env ==" -system! "cp -i .sample.env .env" diff --git a/templates/postcss.config.js b/templates/postcss.config.js deleted file mode 100644 index 9c81e2163..000000000 --- a/templates/postcss.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - plugins: [ - require('postcss-nesting'), - require('autoprefixer'), - require('postcss-normalize') - ], -} - diff --git a/templates/postgresql_database.yml.erb b/templates/postgresql_database.yml.erb deleted file mode 100644 index 8b5a6a105..000000000 --- a/templates/postgresql_database.yml.erb +++ /dev/null @@ -1,20 +0,0 @@ -development: &default - adapter: postgresql - database: <%= app_name %>_development - encoding: utf8 - min_messages: warning - pool: <%%= Integer(ENV.fetch("DB_POOL", 5)) %> - reaping_frequency: <%%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %> - timeout: 5000 - url: <%%= ENV["DATABASE_URL"] %> - -test: - <<: *default - database: <%= app_name %>_test - -production: &deploy - encoding: utf8 - min_messages: warning - pool: <%%= [Integer(ENV.fetch("MAX_THREADS", 5)), Integer(ENV.fetch("DB_POOL", 5))].max %> - timeout: 5000 - url: <%%= ENV.fetch("DATABASE_URL", "") %> diff --git a/templates/rack_mini_profiler.rb b/templates/rack_mini_profiler.rb deleted file mode 100644 index 3f4bc9ee9..000000000 --- a/templates/rack_mini_profiler.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -if ENV["RACK_MINI_PROFILER"].to_i > 0 - require "rack-mini-profiler" - - Rack::MiniProfilerRails.initialize!(Rails.application) -end diff --git a/templates/rails_helper.rb b/templates/rails_helper.rb deleted file mode 100644 index 521f44006..000000000 --- a/templates/rails_helper.rb +++ /dev/null @@ -1,25 +0,0 @@ -ENV["RACK_ENV"] = "test" - -require File.expand_path("../../config/environment", __FILE__) - -if Rails.env.production? - abort("The Rails environment is running in production mode!") -end - -require "rspec/rails" - -Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } - -module SystemTestHelper - # Extend this module in spec/support/system/*.rb - include Formulaic::Dsl -end - -RSpec.configure do |config| - config.include SystemTestHelper, type: :system - config.infer_base_class_for_anonymous_controllers = false - config.infer_spec_type_from_file_location! - config.use_transactional_fixtures = true -end - -ActiveRecord::Migration.maintain_test_schema! diff --git a/templates/sample_env b/templates/sample_env deleted file mode 100644 index e1f1affb5..000000000 --- a/templates/sample_env +++ /dev/null @@ -1,12 +0,0 @@ -# https://github.com/ddollar/forego -ASSET_HOST=localhost:3000 -APPLICATION_HOST=localhost:3000 -PORT=3000 -RACK_ENV=development -REDIS_URL=localhost:6379 -SECRET_KEY_BASE=development_secret -SMTP_ADDRESS=smtp.example.com -SMTP_DOMAIN=example.com -SMTP_PASSWORD=password -SMTP_USERNAME=username -WEB_CONCURRENCY=1 diff --git a/templates/secrets.yml b/templates/secrets.yml deleted file mode 100644 index 585c90684..000000000 --- a/templates/secrets.yml +++ /dev/null @@ -1,8 +0,0 @@ -shared: - secret_key_base: <%%= ENV["SECRET_KEY_BASE"] %> - -development: - -test: - -production: diff --git a/templates/shoulda_matchers_config_rspec.rb b/templates/shoulda_matchers_config_rspec.rb deleted file mode 100644 index 7d045f359..000000000 --- a/templates/shoulda_matchers_config_rspec.rb +++ /dev/null @@ -1,6 +0,0 @@ -Shoulda::Matchers.configure do |config| - config.integrate do |with| - with.test_framework :rspec - with.library :rails - end -end diff --git a/templates/smtp.rb b/templates/smtp.rb deleted file mode 100644 index 0440e09bb..000000000 --- a/templates/smtp.rb +++ /dev/null @@ -1,9 +0,0 @@ -SMTP_SETTINGS = { - address: ENV.fetch("SMTP_ADDRESS"), # example: "smtp.sendgrid.net" - authentication: :plain, - domain: ENV.fetch("SMTP_DOMAIN"), # example: "heroku.com" - enable_starttls_auto: true, - password: ENV.fetch("SMTP_PASSWORD"), - port: "587", - user_name: ENV.fetch("SMTP_USERNAME") -} diff --git a/templates/spec_helper.rb b/templates/spec_helper.rb deleted file mode 100644 index 570dacc82..000000000 --- a/templates/spec_helper.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "webmock/rspec" -require "timecop" - -# http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.syntax = :expect - end - - config.mock_with :rspec do |mocks| - mocks.syntax = :expect - mocks.verify_partial_doubles = true - end - - config.example_status_persistence_file_path = "tmp/rspec_examples.txt" - config.order = :random -end - -WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" -) - -# Only allow Timecop with block syntax -Timecop.safe_mode = true diff --git a/templates/stylelintrc.json b/templates/stylelintrc.json deleted file mode 100644 index 3171f405a..000000000 --- a/templates/stylelintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@thoughtbot/stylelint-config" -} diff --git a/templates/suspenders_gitignore b/templates/suspenders_gitignore deleted file mode 100644 index 32c653ab3..000000000 --- a/templates/suspenders_gitignore +++ /dev/null @@ -1,18 +0,0 @@ -!.keep -*.DS_Store -*.swo -*.swp -.byebug_history -/.bundle -/.env -/coverage/* -/db/*.sqlite3 -/db/*.sqlite3-journal -/log/* -/node_modules -/public/assets -/public/packs -/public/system -/tags -/tmp/* -/yarn-error.log diff --git a/templates/suspenders_layout.html.erb.erb b/templates/suspenders_layout.html.erb.erb deleted file mode 100644 index 36486938e..000000000 --- a/templates/suspenders_layout.html.erb.erb +++ /dev/null @@ -1,23 +0,0 @@ - - - - <%%# - Configure default and controller-, and view-specific titles in - config/locales/en.yml. For more see: - https://github.com/calebthompson/title#usage - %> - <%%= title %> - - - <%%= csrf_meta_tags %> - <%%= csp_meta_tag %> - - <%%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> - <%%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %> - - - <%%= render "flashes" -%> - <%%= yield %> - <%%= render "css_overrides" %> - - diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 000000000..9a5ea7383 --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/spec/support/bundler_stub.rb b/test/dummy/app/assets/images/.keep similarity index 100% rename from spec/support/bundler_stub.rb rename to test/dummy/app/assets/images/.keep diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css new file mode 100644 index 000000000..dcd72732e --- /dev/null +++ b/test/dummy/app/assets/stylesheets/application.css @@ -0,0 +1 @@ +/* Application styles */ diff --git a/test/dummy/app/channels/application_cable/channel.rb b/test/dummy/app/channels/application_cable/channel.rb new file mode 100644 index 000000000..d67269728 --- /dev/null +++ b/test/dummy/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/test/dummy/app/channels/application_cable/connection.rb b/test/dummy/app/channels/application_cable/connection.rb new file mode 100644 index 000000000..0ff5442f4 --- /dev/null +++ b/test/dummy/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/test/dummy/app/controllers/application_controller.rb b/test/dummy/app/controllers/application_controller.rb new file mode 100644 index 000000000..09705d12a --- /dev/null +++ b/test/dummy/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/test/dummy/app/controllers/concerns/.keep b/test/dummy/app/controllers/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/test/dummy/app/jobs/application_job.rb b/test/dummy/app/jobs/application_job.rb new file mode 100644 index 000000000..d394c3d10 --- /dev/null +++ b/test/dummy/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/test/dummy/app/mailers/application_mailer.rb b/test/dummy/app/mailers/application_mailer.rb new file mode 100644 index 000000000..3c34c8148 --- /dev/null +++ b/test/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "from@example.com" + layout "mailer" +end diff --git a/test/dummy/app/models/application_record.rb b/test/dummy/app/models/application_record.rb new file mode 100644 index 000000000..b63caeb8a --- /dev/null +++ b/test/dummy/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + primary_abstract_class +end diff --git a/test/dummy/app/models/concerns/.keep b/test/dummy/app/models/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb new file mode 100644 index 000000000..f72b4ef0e --- /dev/null +++ b/test/dummy/app/views/layouts/application.html.erb @@ -0,0 +1,15 @@ + + + + Dummy + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag "application" %> + + + + <%= yield %> + + diff --git a/test/dummy/app/views/layouts/mailer.html.erb b/test/dummy/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..3aac9002e --- /dev/null +++ b/test/dummy/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/test/dummy/app/views/layouts/mailer.text.erb b/test/dummy/app/views/layouts/mailer.text.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/test/dummy/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/test/dummy/bin/rails b/test/dummy/bin/rails new file mode 100755 index 000000000..efc037749 --- /dev/null +++ b/test/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/test/dummy/bin/rake b/test/dummy/bin/rake new file mode 100755 index 000000000..4fbf10b96 --- /dev/null +++ b/test/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/test/dummy/bin/setup b/test/dummy/bin/setup new file mode 100755 index 000000000..3cd5a9d78 --- /dev/null +++ b/test/dummy/bin/setup @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +require "fileutils" + +# path to your application root. +APP_ROOT = File.expand_path("..", __dir__) + +def system!(*args) + system(*args, exception: true) +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + + puts "\n== Preparing database ==" + system! "bin/rails db:prepare" + + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + puts "\n== Restarting application server ==" + system! "bin/rails restart" +end diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 000000000..4a3c09a68 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,6 @@ +# This file is used by Rack-based servers to start the application. + +require_relative "config/environment" + +run Rails.application +Rails.application.load_server diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 000000000..636d329c2 --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,26 @@ +require_relative "boot" + +require "rails/all" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Dummy + class Application < Rails::Application + config.load_defaults Rails::VERSION::STRING.to_f + + # Please, add to the `ignore` list any other `lib` subdirectories that do + # not contain `.rb` files, or that should not be reloaded or eager loaded. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.autoload_lib(ignore: %w[assets tasks]) + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + end +end diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 000000000..116591a4e --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__) + +require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) +$LOAD_PATH.unshift File.expand_path("../../../lib", __dir__) diff --git a/test/dummy/config/cable.yml b/test/dummy/config/cable.yml new file mode 100644 index 000000000..98367f895 --- /dev/null +++ b/test/dummy/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: dummy_production diff --git a/test/dummy/config/database.yml b/test/dummy/config/database.yml new file mode 100644 index 000000000..796466ba2 --- /dev/null +++ b/test/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite. Versions 3.8.0 and up are supported. +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem "sqlite3" +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: storage/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: storage/test.sqlite3 + +production: + <<: *default + database: storage/production.sqlite3 diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 000000000..cac531577 --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb new file mode 100644 index 000000000..e77b138fe --- /dev/null +++ b/test/dummy/config/environments/development.rb @@ -0,0 +1,73 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.enable_reloading = true + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable server timing + config.server_timing = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true + + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb new file mode 100644 index 000000000..8fddf6e10 --- /dev/null +++ b/test/dummy/config/environments/production.rb @@ -0,0 +1,91 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.enable_reloading = false + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Enable static file serving from the `/public` folder (turn off if using NGINX/Apache for it). + config.public_file_server.enabled = true + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain. + # config.action_cable.mount_path = nil + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true + + # Log to STDOUT by default + config.logger = ActiveSupport::Logger.new($stdout) + .tap { |logger| logger.formatter = ::Logger::Formatter.new } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } + + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] + + # Info include generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } +end diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 000000000..bcb1febb1 --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,64 @@ +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false + + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV["CI"].present? + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + config.cache_store = :null_store + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = :rescuable + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory. + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/test/dummy/config/initializers/content_security_policy.rb b/test/dummy/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..b3076b38f --- /dev/null +++ b/test/dummy/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src style-src) +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/test/dummy/config/initializers/filter_parameter_logging.rb b/test/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..c2d89e28a --- /dev/null +++ b/test/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/test/dummy/config/initializers/inflections.rb b/test/dummy/config/initializers/inflections.rb new file mode 100644 index 000000000..3860f659e --- /dev/null +++ b/test/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/test/dummy/config/initializers/permissions_policy.rb b/test/dummy/config/initializers/permissions_policy.rb new file mode 100644 index 000000000..7db3b9577 --- /dev/null +++ b/test/dummy/config/initializers/permissions_policy.rb @@ -0,0 +1,13 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide HTTP permissions policy. For further +# information see: https://developers.google.com/web/updates/2018/06/feature-policy + +# Rails.application.config.permissions_policy do |policy| +# policy.camera :none +# policy.gyroscope :none +# policy.microphone :none +# policy.usb :none +# policy.fullscreen :self +# policy.payment :self, "https://secure.example.com" +# end diff --git a/test/dummy/config/locales/en.yml b/test/dummy/config/locales/en.yml new file mode 100644 index 000000000..6c349ae5e --- /dev/null +++ b/test/dummy/config/locales/en.yml @@ -0,0 +1,31 @@ +# Files in the config/locales directory are used for internationalization and +# are automatically loaded by Rails. If you want to use locales other than +# English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t "hello" +# +# In views, this is aliased to just `t`: +# +# <%= t("hello") %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more about the API, please read the Rails Internationalization guide +# at https://guides.rubyonrails.org/i18n.html. +# +# Be aware that YAML interprets the following case-insensitive strings as +# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings +# must be quoted to be interpreted as strings. For example: +# +# en: +# "yes": yup +# enabled: "ON" + +en: + hello: "Hello world" diff --git a/test/dummy/config/puma.rb b/test/dummy/config/puma.rb new file mode 100644 index 000000000..afa809b43 --- /dev/null +++ b/test/dummy/config/puma.rb @@ -0,0 +1,35 @@ +# This configuration file will be evaluated by Puma. The top-level methods that +# are invoked here are part of Puma's configuration DSL. For more information +# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. + +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies that the worker count should equal the number of processors in production. +if ENV["RAILS_ENV"] == "production" + require "concurrent-ruby" + worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count }) + workers worker_count if worker_count > 1 +end + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb new file mode 100644 index 000000000..9f768e57d --- /dev/null +++ b/test/dummy/config/routes.rb @@ -0,0 +1,10 @@ +Rails.application.routes.draw do + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + + # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. + # Can be used by load balancers and uptime monitors to verify that the app is live. + get "up" => "rails/health#show", :as => :rails_health_check + + # Defines the root path route ("/") + # root "posts#index" +end diff --git a/test/dummy/config/storage.yml b/test/dummy/config/storage.yml new file mode 100644 index 000000000..4942ab669 --- /dev/null +++ b/test/dummy/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket-<%= Rails.env %> + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket-<%= Rails.env %> + +# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name-<%= Rails.env %> + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/test/dummy/lib/assets/.keep b/test/dummy/lib/assets/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/log/.keep b/test/dummy/log/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/public/404.html b/test/dummy/public/404.html new file mode 100644 index 000000000..2be3af26f --- /dev/null +++ b/test/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/422.html b/test/dummy/public/422.html new file mode 100644 index 000000000..c08eac0d1 --- /dev/null +++ b/test/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/500.html b/test/dummy/public/500.html new file mode 100644 index 000000000..78a030af2 --- /dev/null +++ b/test/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/apple-touch-icon-precomposed.png b/test/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/public/apple-touch-icon.png b/test/dummy/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/public/favicon.ico b/test/dummy/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/storage/.keep b/test/dummy/storage/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/tmp/.keep b/test/dummy/tmp/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/tmp/pids/.keep b/test/dummy/tmp/pids/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/dummy/tmp/storage/.keep b/test/dummy/tmp/storage/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/suspenders_test.rb b/test/suspenders_test.rb new file mode 100644 index 000000000..948ef5022 --- /dev/null +++ b/test/suspenders_test.rb @@ -0,0 +1,15 @@ +require "test_helper" + +class SuspendersTest < ActiveSupport::TestCase + test "it has a version number" do + assert Suspenders::VERSION + end + + test "it has a Rails version number" do + assert Suspenders::RAILS_VERSION + end + + test "it has a Minimum Ruby version number" do + assert Suspenders::MINIMUM_RUBY_VERSION + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 000000000..9f2c11d95 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,14 @@ +# Configure Rails Environment +ENV["RAILS_ENV"] = "test" + +require_relative "../test/dummy/config/environment" +ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)] +require "rails/test_help" + +# Load fixtures from the engine +if ActiveSupport::TestCase.respond_to?(:fixture_paths=) + ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)] + ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths + ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files" + ActiveSupport::TestCase.fixtures :all +end