├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.yml ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── .standard.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── PULL_REQUEST_TEMPLATE.md ├── Procfile ├── Procfile.concurrency ├── Procfile.development ├── README.md ├── Rakefile ├── SECURITY.md ├── app.json ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── images │ │ ├── CodeTriage2012.png │ │ ├── favicon.ico │ │ ├── heroku.svg │ │ ├── logo-dark-text.png │ │ ├── logo.svg │ │ ├── private-avatar.svg │ │ ├── schneems.svg │ │ ├── sponsors │ │ │ └── scout.png │ │ ├── thoughtbot.svg │ │ └── warning.svg │ ├── javascripts │ │ ├── application.js.erb │ │ ├── badge.js │ │ ├── bootstrap.min.js │ │ ├── bootstrap_custom.js │ │ ├── coffee_script_utilities.js.coffee │ │ ├── global.js │ │ ├── homepage.js │ │ ├── preview_link_builder.js.coffee │ │ ├── replace_text.js │ │ ├── tab_navigation.js.coffee │ │ └── user_email_time_of_day.js │ ├── raw │ │ ├── codetriage-logo-white-text-screen.png │ │ ├── codetriage-logo-white-text.ai │ │ ├── codetriage-logo-white-text.eps │ │ ├── codetriage-logo-white-text.png │ │ ├── codetriage-logo.ai │ │ ├── codetriage-logo.eps │ │ ├── codetriage-logo.png │ │ └── codetriage-logo.svg │ └── stylesheets │ │ ├── application.scss │ │ ├── base │ │ ├── _base.scss │ │ ├── _buttons.scss │ │ ├── _forms.scss │ │ ├── _grid-settings.scss │ │ ├── _lists.scss │ │ ├── _tables.scss │ │ ├── _typography.scss │ │ └── _variables.scss │ │ ├── components │ │ ├── _accordion-tabs.scss │ │ ├── _all-languages-list.scss │ │ ├── _avatar.scss │ │ ├── _content-section.scss │ │ ├── _flashes.scss │ │ ├── _full-width-action.scss │ │ ├── _hero.scss │ │ ├── _nav-tabs.scss │ │ ├── _pagination.scss │ │ ├── _repo-badge.scss │ │ ├── _repo-list.scss │ │ ├── _repo.scss │ │ ├── _section-break.scss │ │ ├── _slats-list.scss │ │ ├── _staticish-pages.scss │ │ ├── _subpage-content.scss │ │ ├── _top-bar.scss │ │ ├── _types-filter.scss │ │ └── _user-email.scss │ │ ├── github │ │ ├── markdown-body.css │ │ └── readme.css │ │ ├── layout │ │ ├── _footer.scss │ │ ├── _header.scss │ │ └── _main-application.scss │ │ ├── markdown.scss │ │ ├── pagination.css │ │ └── repo_body.scss ├── controllers │ ├── api_info_controller.rb │ ├── application_controller.rb │ ├── badges_controller.rb │ ├── doc_methods_controller.rb │ ├── issue_assignments_controller.rb │ ├── pages_controller.rb │ ├── repo_based_controller.rb │ ├── repo_subscriptions_controller.rb │ ├── repos_controller.rb │ ├── subscribers_controller.rb │ ├── topics_controller.rb │ ├── university_controller.rb │ ├── users │ │ ├── after_signup_controller.rb │ │ └── omniauth_callbacks_controller.rb │ └── users_controller.rb ├── helpers │ ├── application_helper.rb │ ├── repos_helper.rb │ ├── subscribers_helper.rb │ └── users_helper.rb ├── jobs │ ├── application_job.rb │ ├── background_inactive_email_job.rb │ ├── populate_docs_job.rb │ ├── populate_issues_job.rb │ ├── repo_based_job.rb │ ├── send_daily_triage_email_job.rb │ ├── send_single_triage_email_job.rb │ ├── sentry_job.rb │ ├── subscribe_user_to_docs.rb │ ├── update_repo_info_job.rb │ └── user_based_job.rb ├── mailers │ ├── .gitkeep │ └── user_mailer.rb ├── models │ ├── .gitkeep │ ├── doc_assignment.rb │ ├── doc_class.rb │ ├── doc_comment.rb │ ├── doc_mailer_maker.rb │ ├── doc_method.rb │ ├── email_rate_limit.rb │ ├── git_branchname_generator.rb │ ├── github_fetcher.rb │ ├── github_fetcher │ │ ├── commit_sha.rb │ │ ├── email.rb │ │ ├── issue.rb │ │ ├── issue_comments.rb │ │ ├── issues.rb │ │ ├── repo.rb │ │ ├── repos.rb │ │ ├── resource.rb │ │ └── user.rb │ ├── github_url_from_base_path_line.rb │ ├── issue.rb │ ├── issue_assigner.rb │ ├── issue_assignment.rb │ ├── label.rb │ ├── mail_builder │ │ └── grouped_issues_docs.rb │ ├── random │ │ └── cached_id_query.rb │ ├── repo.rb │ ├── repo_label.rb │ ├── repo_subscription.rb │ └── user.rb ├── services │ ├── git_hub_authenticator.rb │ └── repo_label_assigner.rb └── views │ ├── application │ ├── _down.html.slim │ ├── _flashes.html.slim │ ├── _footer.html.slim │ ├── _head.html.slim │ └── _nav.html.slim │ ├── doc_methods │ └── show.html.slim │ ├── layouts │ ├── _app.html.slim │ ├── application.html.slim │ ├── mail_layout.html.erb │ ├── mail_layout.text.erb │ └── markdown_page.html.slim │ ├── pages │ ├── _repos_with_pagination.html.slim │ ├── index.html.slim │ ├── privacy.html.slim │ ├── support.html.slim │ └── what.html.erb │ ├── repo_subscriptions │ └── _list.html.slim │ ├── repos │ ├── _badge.html.slim │ ├── _docs.html.slim │ ├── _issues.html.slim │ ├── _repo.html.slim │ ├── edit.html.slim │ ├── list.html.slim │ ├── new.html.slim │ └── show.html.slim │ ├── shared │ └── _add_repos_list.html.slim │ ├── subscribers │ ├── _avatars.html.slim │ └── show.html.slim │ ├── topics │ └── show.html.slim │ ├── university │ ├── example_app.md.erb │ ├── index.md.erb │ ├── picking_a_repo.md.erb │ ├── rebase.md.erb │ ├── reproduction_code.md.erb │ └── squash.md.erb │ ├── user_mailer │ ├── daily_docs.md.erb │ ├── invalid_token.md.erb │ ├── poke_inactive.md.erb │ ├── send_daily_triage.md.erb │ ├── send_triage.md.erb │ └── spam.md.erb │ └── users │ ├── _form.html.slim │ ├── after_signup │ └── set_privacy.html.slim │ ├── edit.html.slim │ ├── show.html.slim │ └── token_delete.html.slim ├── bin ├── bundle ├── puma ├── pumactl ├── rails ├── rake ├── setup ├── update └── yarn ├── config.ru ├── config ├── application.rb ├── boot.rb ├── cable.yml ├── database.ci.yml ├── database.example.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── backlog.rb │ ├── backtrace_silencers.rb │ ├── content_security_policy.rb │ ├── cookie_rotator.rb │ ├── cookies_serializer.rb │ ├── cors.rb │ ├── covid.rb │ ├── devise.rb │ ├── feature_policy.rb │ ├── filter_parameter_logging.rb │ ├── git_hub_bub.rb │ ├── inflections.rb │ ├── mail.rb │ ├── mime_types.rb │ ├── mini-profiler.rb │ ├── new_framework_defaults.rb │ ├── new_framework_defaults_5_2.rb │ ├── new_framework_defaults_6_0.rb │ ├── new_framework_defaults_6_1.rb │ ├── new_framework_defaults_7_0.rb │ ├── permissions_policy.rb │ ├── puma_worker_killer.rb │ ├── request_forgery_protection.rb │ ├── sentry.rb │ ├── session_store.rb │ ├── sidekiq.rb │ ├── silence_warnings.rb │ ├── the_lone_dyno.rb │ ├── time_formats.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ └── en.yml ├── newrelic.yml ├── puma.rb ├── routes.rb ├── scout_apm.yml ├── secrets.yml ├── sitemap.rb └── storage.yml ├── db ├── migrate │ ├── 20120222223509_devise_create_users.rb │ ├── 20120222231841_user_data.rb │ ├── 20120518083745_create_issues.rb │ ├── 20120518085406_create_repo_subscriptions.rb │ ├── 20120518090213_create_issue_assignments.rb │ ├── 20120518091140_create_repos.rb │ ├── 20120620000230_add_github_to_users.rb │ ├── 20120622203236_add_repos_to_issues.rb │ ├── 20120622233057_issue_titles.rb │ ├── 20120622235822_add_user_and_repo_to_repo_subscription.rb │ ├── 20120624204958_add_last_sent_at_to_repo_sub.rb │ ├── 20120624212352_add_html_url_to_issues.rb │ ├── 20120624213335_add_status_to_issues.rb │ ├── 20120627213051_add_repo_sub_to_issue_assignment.rb │ ├── 20120707182259_add_admin_to_users.rb │ ├── 20121106072214_repo_issue_counter_cache.rb │ ├── 20121110213717_add_avatar_url_to_users.rb │ ├── 20121112100015_add_name_to_users.rb │ ├── 20121120203919_add_language_and_description_to_repo.rb │ ├── 20121127163516_add_privacy_to_users.rb │ ├── 20121127171308_add_full_name_to_repos.rb │ ├── 20121128162942_add_notes_to_repo.rb │ ├── 20130222201747_add_favorite_languages_to_user.rb │ ├── 20130312023533_add_email_limit_to_repo_subscriptions.rb │ ├── 20130503183402_add_daily_issue_limit_to_user.rb │ ├── 20130803144944_update_private_attribute_of_user.rb │ ├── 20130918055659_add_pr_attached_to_issues.rb │ ├── 20130918060600_add_skip_issues_with_pr_to_users.rb │ ├── 20131107042958_add_delete_token_to_users.rb │ ├── 20140524120051_add_click_to_issue_assignment.rb │ ├── 20140621155109_add_delievered_to_issue_assignment.rb │ ├── 20140710161559_store_github_request_errors.rb │ ├── 20140710164307_remove_user_id_from_issue_assignments.rb │ ├── 20150629002651_remove_repo_name_from_repo_subscriptions.rb │ ├── 20150629010617_remove_user_name_from_repo_subscriptions.rb │ ├── 20151007212330_create_data_dumps.rb │ ├── 20151021160718_add_index_to_issues.rb │ ├── 20151214120117_enable_pg_stat_extension.rb │ ├── 20160321152204_create_docs_doctor_integration.rb │ ├── 20160404140129_add_click_to_doc_assignments.rb │ ├── 20160404173429_remove_user_from_doc_assignments.rb │ ├── 20160606060546_add_email_frequency_to_users.rb │ ├── 20160613220116_change_issues_title_to_text.rb │ ├── 20160827023209_add_stars_count_to_repos.rb │ ├── 20160827073041_update_stars_count_of_repos.rb │ ├── 20160927195642_add_index_to_repo_subscription_id.rb │ ├── 20170203143323_add_email_time_of_day_to_users.rb │ ├── 20170516193426_repos_name_index.rb │ ├── 20170523195422_add_language_index.rb │ ├── 20170604190958_add_old_token_to_users.rb │ ├── 20170619152237_add_index_to_issues_count.rb │ ├── 20170622201545_add_created_at_index_to_issues.rb │ ├── 20170626162701_make_multi_index.rb │ ├── 20170627024417_add_index_to_doc_method.rb │ ├── 20170629151616_add_unique_index_to_repos.rb │ ├── 20170629230855_index_full_name_of_repos.rb │ ├── 20170629233102_add_foreign_key_to_repo_subscriptions.rb │ ├── 20170630002100_add_foreign_key_for_repo_users.rb │ ├── 20170630191148_add_index_to_issue_on_repo_id_and_number.rb │ ├── 20170630192013_add_index_to_doc_method_creation.rb │ ├── 20170801021151_default_value_for_max_issues.rb │ ├── 20171125012313_add_partial_index_to_id.rb │ ├── 20171125013100_remove_partial_index_to_id.rb │ ├── 20171125013319_add_index_for_pagination.rb │ ├── 20171125202301_fix_doc_methods_indexes.rb │ ├── 20171125212307_add_subscribers_count_to_repos.rb │ ├── 20180716144937_add_streak_to_users.rb │ ├── 20180820155654_add_last_email_at_to_user.rb │ ├── 20190322102229_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb │ ├── 20190809190610_add_missing_indexes.rb │ ├── 20191010023214_add_docs_subscriber_count_to_repos.rb │ ├── 20191014201819_drop_unused_indexes.rb │ ├── 20191017202913_add_removed_from_github_to_repo.rb │ ├── 20191025030201_add_unique_index_number_repo_id.rb │ ├── 20191025191255_add_updated_at_index_to_issues.rb │ ├── 20191029194525_make_timestamps_not_nullable.rb │ ├── 20191031142027_add_comment_to_doc_method.rb │ ├── 20191031144636_add_unique_indexes_to_doc_methods.rb │ ├── 20201115123024_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20201115123025_create_active_storage_variant_records.active_storage.rb │ ├── 20220908011235_add_htos_promo_to_user.rb │ ├── 20221004010742_create_labels_table.rb │ ├── 20221004010749_create_repo_labels_table.rb │ ├── 20221010011048_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb │ ├── 20221013212959_add_archived_column_to_repo.rb │ └── 20221228065556_add_index_subscriber_count.rb ├── schema.rb ├── seeds.rb └── structure.sql ├── doc └── README_FOR_APP ├── heroku.yml ├── lib ├── assets │ └── .gitkeep ├── dependency_parser │ ├── php │ │ └── parse.rb │ └── ruby │ │ └── parse.rb ├── docs_doctor │ ├── doc_obj.rb │ ├── loader.rb │ ├── parser.rb │ ├── parsers │ │ └── ruby │ │ │ ├── require 'atomic' │ │ │ └── yard.rb │ ├── runner.rb │ └── task.rb ├── sorted_repo_collection.rb └── tasks │ ├── .gitkeep │ ├── performance.rake │ ├── schedule.rake │ └── test.rake ├── log └── .gitkeep ├── package.json ├── perf.rake ├── perf_scripts ├── cache_version.rb ├── dirty_tracking.rb ├── partial_cache.rb ├── partial_cache │ └── test │ │ ├── _customer.html.erb │ │ ├── _render_collection.html.erb │ │ └── _render_collection_with_cache.html.erb └── respond_to.rb ├── public ├── 404.html ├── 422.html ├── 500.html └── robots.txt ├── scratch.rb ├── test ├── dependency_parsers │ ├── php_parser_test.rb │ └── ruby_parser_test.rb ├── emails │ └── send_daily_triage_email_test.rb ├── fixtures │ ├── .gitkeep │ ├── doc_methods.yml │ ├── files │ │ └── composer.lock │ ├── issue_assignments.yml │ ├── issues.yml │ ├── repo_subscriptions.yml │ ├── repos.yml │ └── users.yml ├── functional │ ├── .gitkeep │ ├── after_register_controller_test.rb │ ├── doc_methods_controller_test.rb │ ├── issue_assignments_controller_test.rb │ ├── omniauth_callbacks_controller_test.rb │ ├── pages_controller_test.rb │ ├── repo_subscriptions_controller_test.rb │ ├── repos_controller_test.rb │ ├── subscribers_controller_test.rb │ ├── topics_controller_test.rb │ ├── user_mailer_test.rb │ └── users_controller_test.rb ├── helpers │ ├── .gitkeep │ └── application_helper_test.rb ├── integration │ ├── .gitkeep │ ├── adding_repos_test.rb │ ├── filtering_language_test.rb │ ├── maintaining_repo_subscriptions_test.rb │ ├── repos_test.rb │ ├── user_session_test.rb │ ├── user_unsubscribes_test.rb │ └── user_update_test.rb ├── jobs │ ├── background_inactive_email_job_test.rb │ ├── parse_docs_test.rb │ ├── populate_issues_job_test.rb │ ├── send_daily_triage_email_job_test.rb │ ├── send_single_triage_email_job_test.rb │ └── update_repo_info_job_test.rb ├── mailers │ └── previews │ │ └── user_preview.rb ├── test_helper.rb ├── unit │ ├── .gitkeep │ ├── email_rate_limit_test.rb │ ├── git_branchname_generator_test.rb │ ├── git_hub_authenticator_test.rb │ ├── github_fetcher │ │ ├── commit_sha_test.rb │ │ ├── email_test.rb │ │ ├── issue_comments_test.rb │ │ ├── issue_test.rb │ │ ├── issues_test.rb │ │ ├── repo_test.rb │ │ ├── repos_test.rb │ │ ├── resource_test.rb │ │ └── user_test.rb │ ├── helpers │ │ └── after_register_helper_test.rb │ ├── issue_assignment_test.rb │ ├── issue_test.rb │ ├── mail_builder │ │ └── grouped_issues_docs_test.rb │ ├── repo_labels_assigner_test.rb │ ├── repo_subscriptions_test.rb │ ├── repo_test.rb │ ├── sorted_repo_collection_test.rb │ └── user_test.rb └── vcr_cassettes │ ├── bad_fetch_emails.yml │ ├── blank_repo.yml │ ├── commenting_users_issue.yml │ ├── create_duplicate_repo_refinery.yml │ ├── create_repo_refinery.yml │ ├── create_repo_without_issues.yml │ ├── dependency_parser │ └── rubygems.yml │ ├── fetch_emails.yml │ ├── fetch_github_user.yml │ ├── fetch_github_user_invalid_check.yml │ ├── fetch_github_user_valid_check.yml │ ├── fetch_issue.yml │ ├── fetch_issue_commenters.yml │ ├── fetch_issue_comments.yml │ ├── fetch_labels_for_repo.yml │ ├── fetcher_commit_sha.yml │ ├── fetcher_more_starred_repos_for_user.yml │ ├── fetcher_owned_repos_for_user.yml │ ├── fetcher_owned_repos_for_user_first_100.yml │ ├── fetcher_starred_repos_for_user.yml │ ├── fetcher_subscribed_repos_for_user.yml │ ├── issue_triage_sandbox_fake_api_responses.yml │ ├── issue_triage_sandbox_fetch_issues.yml │ ├── my_repos.yml │ ├── rails_rails_fetch_issues.yml │ ├── rails_rails_fetch_issues_page_two.yml │ ├── repo_info.yml │ ├── repo_info_error.yml │ ├── repo_populate_docs.yml │ └── update_repo_info_schneems │ └── sextant.yml ├── vendor ├── assets │ ├── javascripts │ │ ├── .gitkeep │ │ └── raven.js │ └── stylesheets │ │ └── .gitkeep └── plugins │ └── .gitkeep └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs 2 | # @see http://editorconfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | indent_style = spaces 11 | tab_width = 2 12 | 13 | [{*.{rb,erb,js,coffee,json,yml,css,scss,sh,markdown,md,html}] 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | 12 | 13 | ## To reproduce 14 | Steps to reproduce the behavior: 15 | 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | ## Expected behavior 22 | 23 | 24 | ## Actual behavior 25 | 26 | 27 | ## Screenshots 28 | 29 | 30 | ## Additional context 31 | 32 | 33 | ## Your Environment 34 | 35 | * Version used: 36 | * Browser Name and version: 37 | * Operating System and version (desktop or mobile): 38 | * Link to your project: 39 | 40 | ## Possible Solution 41 | 42 | 43 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: neat 10 | versions: 11 | - "< 4, >= 3.a" 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | base: 6 | runs-on: ubuntu-latest 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | ruby: ["3.1"] 11 | name: Running tests with Ruby ${{ matrix.ruby }} 12 | services: 13 | postgres: 14 | image: postgres:12 15 | env: 16 | POSTGRES_DB: triage_test 17 | POSTGRES_PASSWORD: password 18 | POSTGRES_USER: postgres 19 | ports: ["5432:5432"] 20 | env: 21 | BUNDLE_GEMFILE: Gemfile 22 | 23 | steps: 24 | - name: Checkout code 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup Ruby 28 | uses: ruby/setup-ruby@v1 29 | with: 30 | ruby-version: ${{ matrix.ruby }} 31 | bundler-cache: true 32 | - name: Linting 33 | run: | 34 | bundle exec standardrb 35 | - name: Setup database 36 | run: | 37 | cp config/database.ci.yml config/database.yml 38 | RAILS_ENV=test bundle exec rake db:create db:schema:load 39 | - name: Run tests 40 | run: bin/rake test 41 | - name: Ensure seed task still works 42 | run: RAILS_ENV=test bin/rails db:seed 43 | 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile ~/.gitignore_global 6 | 7 | # Ignore bundler config 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | 13 | # Ignore all logfiles and tempfiles. 14 | /log/*.log 15 | /tmp 16 | 17 | .DS_Store 18 | .rvmrc 19 | .ruby-version 20 | .ruby-gemset 21 | 22 | 23 | .env 24 | dump.rdb 25 | 26 | # Code test coverage reports 27 | /coverage 28 | 29 | # ignore personal settings 30 | /config/database.yml 31 | 32 | public/assets 33 | 34 | # ignore vendor/bundle 35 | vendor/bundle 36 | tags 37 | 38 | config/secrets.yml.key -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | ruby_version: 3.1 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2012 Schneems 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: jemalloc.sh bin/puma -C config/puma.rb 2 | worker: jemalloc.sh bundle exec sidekiq -q default -q mailers -c ${SIDEKIQ_CONCURRENCY:-5} 3 | release: RUBYOPT=--jit bundle exec rake db:migrate 4 | -------------------------------------------------------------------------------- /Procfile.concurrency: -------------------------------------------------------------------------------- 1 | console: rails c 2 | 3 | -------------------------------------------------------------------------------- /Procfile.development: -------------------------------------------------------------------------------- 1 | web: bin/puma -C config/puma.rb 2 | worker: bundle exec sidekiq -q default -q mailers -c ${SIDEKIQ_CONCURRENCY:-5} 3 | release: bundle exec rake db:migrate 4 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | main branch | :white_check_mark: | 11 | 12 | 13 | ## Reporting a Vulnerability 14 | 15 | Contact using the email address on https://github.com/schneems/ profile. 16 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Code Triage ", 3 | "description": "Helping you contribute to open source since 2013", 4 | "website": "https://www.codetriage.com/", 5 | "repository": "https://github.com/codetriage/codetriage", 6 | "scripts": { 7 | "postdeploy": "rake db:schema:load db:migrate db:seed", 8 | "test": "bundle exec standardrb && bin/rails test && rails db:seed" 9 | }, 10 | "env": { 11 | "DEVISE_SECRET_KEY": "foo", 12 | "DEVISE_SECRET_TOKEN": "bar", 13 | "WEB_CONCURRENCY": "1" 14 | }, 15 | "addons": [ 16 | "heroku-postgresql:in-dyno", 17 | "heroku-redis:in-dyno", 18 | "memcachier" 19 | ], 20 | "buildpacks": [ 21 | { 22 | "url": "https://github.com/mojodna/heroku-buildpack-jemalloc.git" 23 | }, 24 | { 25 | "url": "heroku/nodejs" 26 | }, 27 | { 28 | "url": "heroku/ruby" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link application.js 2 | //= link application.css 3 | //= link markdown.css 4 | //= link_tree ../images 5 | -------------------------------------------------------------------------------- /app/assets/images/CodeTriage2012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/images/CodeTriage2012.png -------------------------------------------------------------------------------- /app/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/images/favicon.ico -------------------------------------------------------------------------------- /app/assets/images/heroku.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/assets/images/logo-dark-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/images/logo-dark-text.png -------------------------------------------------------------------------------- /app/assets/images/private-avatar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/sponsors/scout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/images/sponsors/scout.png -------------------------------------------------------------------------------- /app/assets/images/thoughtbot.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /app/assets/images/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js.erb: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // the compiled file. 9 | // 10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD 11 | // GO AFTER THE REQUIRES BELOW. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require local-time 16 | //= require bootstrap.min 17 | //= require bootstrap_custom 18 | //= require coffee_script_utilities 19 | //= require preview_link_builder 20 | //= require tab_navigation 21 | //= require global 22 | //= require badge.js 23 | //= require homepage.js 24 | //= require user_email_time_of_day.js 25 | //= require raven.js 26 | 27 | Raven.config("<%= ENV['SENTRY_DSN_PUBLIC'] %>", { 28 | release: "<%= Raven.configuration.release %>", 29 | environment: "<%= Rails.env %>", 30 | ignoreErrors: [ 31 | // Error generated by a bug in auto-fill library from browser 32 | // https://github.com/getsentry/sentry/issues/5267 33 | /Blocked a frame with origin/, 34 | ] 35 | }).install(); 36 | -------------------------------------------------------------------------------- /app/assets/javascripts/badge.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('.accordion-tabs').on('click', 'li > a.tab-link', function(event) { 3 | if (!$(this).hasClass('is-active')) { 4 | event.preventDefault(); 5 | var accordionTabs = $(this).closest('.accordion-tabs'); 6 | accordionTabs.find('.is-open').removeClass('is-open').hide(); 7 | 8 | $(this).next().toggleClass('is-open').show(); 9 | accordionTabs.find('.is-active').removeClass('is-active'); 10 | $(this).addClass('is-active'); 11 | } else { 12 | event.preventDefault(); 13 | } 14 | }); 15 | }) 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/bootstrap_custom.js: -------------------------------------------------------------------------------- 1 | $('.nav-tabs li a').click(function(e){ 2 | e.preventDefault(); 3 | e.stopImmediatePropagation(); 4 | $(this).tab('show'); 5 | }); 6 | -------------------------------------------------------------------------------- /app/assets/javascripts/coffee_script_utilities.js.coffee: -------------------------------------------------------------------------------- 1 | # Creates a namespaced class or method 2 | # 3 | # Example usages: 4 | # namespace 'Foo.Bar', (exports) -> 5 | # class export.Baz 6 | # ... 7 | # namespace 'Foo.Baz', (exports) -> 8 | # exports.alertFoo = -> 9 | # alert 'foo' 10 | 11 | window.namespace = (target, name, block) -> 12 | [target, name, block] = [(if typeof exports isnt 'undefined' then exports else window), arguments...] if arguments.length < 3 13 | top = target 14 | target = target[item] or= {} for item in name.split '.' 15 | block target, top 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/global.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function(){ 2 | new Codetriage.TabNavigation(); 3 | new Codetriage.previewLinkBuilder(); 4 | }); 5 | -------------------------------------------------------------------------------- /app/assets/javascripts/preview_link_builder.js.coffee: -------------------------------------------------------------------------------- 1 | namespace 'Codetriage', (exports) -> 2 | class exports.previewLinkBuilder 3 | constructor: (customOptions = {}) -> 4 | defaultOptions = { 5 | "userNameInput" : ".preview_user_name", 6 | "userRepoNameInput" : ".preview_repo_name", 7 | "previewLink" : "#repo_preview" 8 | } 9 | 10 | @options = $.extend({}, defaultOptions, customOptions) 11 | @repoPreviewAnchorTag = $("#{@options.previewLink} > a") 12 | @updatePreviewLink() 13 | @updatePreviewLinkOnKeyup() 14 | 15 | createGithubUrl: -> 16 | userName = $(@options.userNameInput).val()?.trim() 17 | repoName = $(@options.userRepoNameInput).val()?.trim() 18 | "https://github.com/#{userName}/#{repoName}" 19 | 20 | checkPreviewUrl: -> 21 | if @repoPreviewAnchorTag.attr('href') == "https://github.com//" 22 | $(@options.previewLink).fadeOut(300) 23 | else 24 | $(@options.previewLink).fadeIn(300) 25 | 26 | updatePreviewLink: -> 27 | @repoPreviewAnchorTag.html(@createGithubUrl()).attr('href',@createGithubUrl()) 28 | @checkPreviewUrl() 29 | 30 | updatePreviewLinkOnKeyup: -> 31 | $(document).delegate @options.userNameInput, "keyup", => 32 | @updatePreviewLink() 33 | 34 | $(document).delegate @options.userRepoNameInput, "keyup", => 35 | @updatePreviewLink() -------------------------------------------------------------------------------- /app/assets/javascripts/replace_text.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery replaceText - v1.1 - 11/21/2009 3 | * http://benalman.com/projects/jquery-replacetext-plugin/ 4 | * 5 | * Copyright (c) 2009 "Cowboy" Ben Alman 6 | * Dual licensed under the MIT and GPL licenses. 7 | * http://benalman.com/about/license/ 8 | */ 9 | (function($){$.fn.replaceText=function(b,a,c){return this.each(function(){var f=this.firstChild,g,e,d=[];if(f){do{if(f.nodeType===3){g=f.nodeValue;e=g.replace(b,a);if(e!==g){if(!c&&/ 2 | class exports.TabNavigation 3 | constructor: (options = {}) -> 4 | @tabItem = $("a[data-toggle]") 5 | @locationHash = location.hash 6 | @defaultLocation() unless @locationHash 7 | @watchHistory() 8 | @bindDataToggleTabEvent() 9 | @showTabLocation() if @locationHash 10 | 11 | defaultLocation: -> 12 | $("#repo-tabs a:first").tab 'show' 13 | 14 | watchHistory: -> 15 | $(window).on "popstate", => 16 | @locationHash = location.hash or @tabItem.first().attr("href") 17 | @showTabLocation() 18 | 19 | bindDataToggleTabEvent: -> 20 | @tabItem.on "click", (event) => 21 | event.preventDefault() 22 | @locationHash = $(event.target).attr('href') 23 | location.hash = @locationHash 24 | @showTabLocation() 25 | 26 | showTabLocation: -> 27 | $("a[href='#{@locationHash}']").tab "show" -------------------------------------------------------------------------------- /app/assets/javascripts/user_email_time_of_day.js: -------------------------------------------------------------------------------- 1 | 2 | // Display options in select box in local time 3 | $(document).ready(function(){ 4 | 5 | $("#user_email_time_of_day option") 6 | .toArray() 7 | .forEach(function(element) { 8 | var time = new Date(element.value); 9 | element.text = LocalTime.strftime(time, "%H:%M %Z"); 10 | }) 11 | 12 | $("#user_email_time_of_day").html($("#user_email_time_of_day option").sort(function (a, b) { 13 | return a.text == b.text ? 0 : a.text < b.text ? -1 : 1 14 | })) 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo-white-text-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo-white-text-screen.png -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo-white-text.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo-white-text.ai -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo-white-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo-white-text.png -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo.ai -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo.eps -------------------------------------------------------------------------------- /app/assets/raw/codetriage-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/app/assets/raw/codetriage-logo.png -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | @import "normalize-rails"; 2 | @import "bourbon"; 3 | @import "neat"; 4 | @import "base/base"; 5 | 6 | @import "layout/*"; 7 | @import "components/*"; 8 | @import "markdown"; 9 | @import "repo_body"; 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/_base.scss: -------------------------------------------------------------------------------- 1 | // Bitters 1.1.0 2 | // http://bitters.bourbon.io 3 | // Copyright 2013-2015 thoughtbot, inc. 4 | // MIT License 5 | 6 | @import "variables"; 7 | 8 | // Neat Settings -- uncomment if using Neat -- must be imported before Neat 9 | // @import "grid-settings"; 10 | 11 | @import "buttons"; 12 | @import "forms"; 13 | @import "lists"; 14 | @import "tables"; 15 | @import "typography"; 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/_buttons.scss: -------------------------------------------------------------------------------- 1 | input[type="submit"].btn-danger { 2 | background-color: $codetriage-red; 3 | 4 | &:hover { 5 | background-color: shade($codetriage-red, 20%); 6 | } 7 | } 8 | 9 | .button, 10 | #{$all-buttons} { 11 | appearance: none; 12 | background-color: $action-color; 13 | border-radius: $base-border-radius; 14 | box-shadow: 0 1px 2px darken($base-background-color, 5%); 15 | border: 0; 16 | color: #fff; 17 | cursor: pointer; 18 | display: inline-block; 19 | font-family: $base-font-family; 20 | font-size: 0.875rem; 21 | font-weight: 600; 22 | letter-spacing: 1px; 23 | line-height: 1; 24 | padding: ($small-spacing * 1.5) $base-spacing; 25 | text-decoration: none; 26 | text-transform: uppercase; 27 | transition: background-color $base-duration $base-timing; 28 | user-select: none; 29 | vertical-align: middle; 30 | white-space: nowrap; 31 | 32 | &:hover, 33 | &:focus { 34 | background-color: shade($action-color, 20%); 35 | color: #fff; 36 | } 37 | 38 | &:disabled { 39 | cursor: not-allowed; 40 | opacity: 0.5; 41 | 42 | &:hover { 43 | background-color: $action-color; 44 | } 45 | } 46 | 47 | &.inactive { 48 | cursor: not-allowed; 49 | opacity: 0.5; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/_grid-settings.scss: -------------------------------------------------------------------------------- 1 | @import "neat-helpers"; // or "../neat/neat-helpers" when not in Rails 2 | 3 | // Neat Overrides 4 | // $column: 90px; 5 | // $gutter: 30px; 6 | // $grid-columns: 12; 7 | // $max-width: 1200px; 8 | 9 | // Neat Breakpoints 10 | $medium-screen: 600px; 11 | $large-screen: 900px; 12 | 13 | $medium-screen-up: new-breakpoint(min-width $medium-screen 4); 14 | $large-screen-up: new-breakpoint(min-width $large-screen 8); 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/_lists.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | list-style-type: none; 3 | } 4 | 5 | ul, 6 | ol { 7 | margin: 0; 8 | padding: 0; 9 | 10 | &%default-ul { 11 | list-style-type: disc; 12 | margin-bottom: $small-spacing; 13 | padding-left: $base-spacing; 14 | } 15 | 16 | &%default-ol { 17 | list-style-type: decimal; 18 | margin-bottom: $small-spacing; 19 | padding-left: $base-spacing; 20 | } 21 | } 22 | 23 | dl { 24 | margin-bottom: $small-spacing; 25 | 26 | dt { 27 | font-weight: bold; 28 | margin-top: $small-spacing; 29 | } 30 | 31 | dd { 32 | margin: 0; 33 | } 34 | } 35 | 36 | 37 | .bullets { 38 | list-style-type: disc; 39 | padding: 1em 0 0 2em; 40 | } 41 | 42 | ol.normal-ol { 43 | padding: 0 0 inherit; 44 | } 45 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/_tables.scss: -------------------------------------------------------------------------------- 1 | table { 2 | border-collapse: collapse; 3 | font-feature-settings: "kern", "liga", "tnum"; 4 | margin: $small-spacing 0; 5 | table-layout: fixed; 6 | // width: 100%; // Breaks rack-mini-profiler 7 | } 8 | 9 | th { 10 | border-bottom: 1px solid shade($base-border-color, 25%); 11 | font-weight: 600; 12 | padding: $small-spacing 0; 13 | text-align: left; 14 | } 15 | 16 | td { 17 | border-bottom: $base-border; 18 | padding: $small-spacing 0; 19 | } 20 | 21 | tr, 22 | td, 23 | th { 24 | vertical-align: middle; 25 | } 26 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_accordion-tabs.scss: -------------------------------------------------------------------------------- 1 | .accordion-tabs { 2 | $large-screen: 54em !default; 3 | 4 | @include clearfix; 5 | padding: 0; 6 | 7 | .tab-header-and-content { 8 | list-style: none; 9 | 10 | @include media($large-screen) { 11 | display: inline; 12 | } 13 | } 14 | 15 | .tab-link { 16 | display: block; 17 | padding-right: 1em; 18 | 19 | @include media($large-screen) { 20 | display: inline-block; 21 | } 22 | } 23 | 24 | .is-active { 25 | color: $codetriage-red; 26 | } 27 | 28 | .tab-content { 29 | display: none; 30 | width: 100%; 31 | margin-top: $small-spacing; 32 | float: left; 33 | 34 | &.is-open { 35 | display: block; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_all-languages-list.scss: -------------------------------------------------------------------------------- 1 | .all-languages-list { 2 | @include clearfix; 3 | } 4 | 5 | .language-item { 6 | position: relative; 7 | 8 | @include media(max-width 699px) { 9 | @include omega(2n); 10 | @include span-columns(6); 11 | } 12 | 13 | @include media(700px) { 14 | @include omega(4n); 15 | @include span-columns(3); 16 | } 17 | 18 | input[type='checkbox'] { 19 | width: 1rem; 20 | cursor: pointer; 21 | 22 | + label { 23 | cursor: pointer; 24 | margin-bottom: $small-spacing; 25 | 26 | &::before { 27 | @include position(absolute, 3px null null -2px); 28 | @include size(1.1rem, 1rem); 29 | background-color: $codetriage-blue; 30 | border-radius: $base-border-radius; 31 | color: $base-background-color; 32 | content: ""; 33 | display: inline-block; 34 | line-height: 1rem; 35 | pointer-events: none; 36 | text-align: center; 37 | } 38 | } 39 | 40 | &:checked + label { 41 | &::before { 42 | background-color: $white; 43 | content: "×"; 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_avatar.scss: -------------------------------------------------------------------------------- 1 | .avatars-list { 2 | @include row; 3 | 4 | li { 5 | margin-bottom: $small-spacing; 6 | 7 | @include media(max-width 24.9375rem) { 8 | @include omega(2n); 9 | @include span-columns(6); 10 | } 11 | 12 | @include media(min-width 25rem max-width 42.9375rem) { 13 | @include omega(3n); 14 | @include span-columns(4); 15 | } 16 | 17 | @include media(43rem) { 18 | @include omega(6n); 19 | @include span-columns(2); 20 | } 21 | } 22 | } 23 | 24 | .avatar-image { 25 | border-radius: $base-border-radius; 26 | width: 100%; 27 | } 28 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_content-section.scss: -------------------------------------------------------------------------------- 1 | .content-section { 2 | @include clearfix; 3 | border-bottom: $content-border; 4 | padding: $base-spacing 0; 5 | 6 | &:last-of-type { 7 | border-bottom: 0; 8 | margin-bottom: 0; 9 | padding-bottom: 0; 10 | } 11 | } 12 | 13 | .content-section-title { 14 | font-size: 1.375rem; 15 | margin-bottom: 1rem; 16 | color: $base-font-color; 17 | } 18 | 19 | .selectable p { 20 | margin: 0; 21 | 22 | &::before { 23 | content: "$ " 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_flashes.scss: -------------------------------------------------------------------------------- 1 | @mixin flash($color) { 2 | background-color: $color; 3 | color: darken($color, 60%); 4 | display: block; 5 | padding: $base-spacing $small-spacing; 6 | text-align: center; 7 | 8 | p { 9 | margin-bottom: 0; 10 | } 11 | 12 | a { 13 | color: darken($color, 70%); 14 | text-decoration: underline; 15 | 16 | &:focus, 17 | &:hover { 18 | color: darken($color, 90%); 19 | } 20 | } 21 | } 22 | 23 | .flash-alert { 24 | @include flash($alert-color); 25 | } 26 | 27 | .flash-error { 28 | @include flash($error-color); 29 | } 30 | 31 | .flash-notice { 32 | @include flash($notice-color); 33 | } 34 | 35 | .flash-success { 36 | @include flash($success-color); 37 | } 38 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_full-width-action.scss: -------------------------------------------------------------------------------- 1 | .full-width-action { 2 | clear: both; 3 | display: block; 4 | margin-top: $base-spacing; 5 | text-align: center; 6 | width: 100%; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_hero.scss: -------------------------------------------------------------------------------- 1 | .hero { 2 | max-width: 55em; 3 | margin: 0 auto; 4 | padding-top: 4rem; 5 | text-align: center; 6 | 7 | .button { 8 | margin-top: 3rem; 9 | } 10 | 11 | .github-icon { 12 | @include position(relative, 2px null null null); 13 | @include size(1rem); 14 | fill: $base-font-color; 15 | margin-right: 1rem; 16 | } 17 | } 18 | 19 | .hero-title-primary { 20 | color: $base-font-color; 21 | font-size: 2.5rem; 22 | margin-bottom: $base-spacing; 23 | } 24 | 25 | .hero-title-secondary { 26 | font-size: 1.25rem; 27 | line-height: 1.5; 28 | font-weight: 100; 29 | margin: 0 auto; 30 | max-width: 50rem; 31 | } 32 | 33 | .hero-repo-list-container { 34 | text-align: center; 35 | 36 | .repo-list { 37 | justify-content: center; 38 | text-align: left; 39 | } 40 | 41 | .repo-item { 42 | &:last-of-type { 43 | margin-right: 0; 44 | } 45 | } 46 | 47 | .button { 48 | &:not(:last-of-type) { 49 | margin-right: $base-spacing; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_nav-tabs.scss: -------------------------------------------------------------------------------- 1 | .nav-tabs { 2 | @include row; 3 | border-left: $content-border; 4 | border-right: $content-border; 5 | border-top: $content-border; 6 | } 7 | 8 | .nav-tabs-item { 9 | padding: $small-spacing; 10 | text-align: center; 11 | 12 | @include media(31rem) { 13 | float: left; 14 | width: 33.3333%; 15 | } 16 | 17 | a { 18 | display: block; 19 | } 20 | 21 | &:not(:last-child) { 22 | border-right: $content-border; 23 | } 24 | 25 | &.active { 26 | background-color: $action-color; 27 | 28 | a { 29 | color: $base-background-color; 30 | } 31 | } 32 | } 33 | 34 | .tab-pane { 35 | display: none; 36 | 37 | &.active { 38 | display: block; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_pagination.scss: -------------------------------------------------------------------------------- 1 | .pagination { 2 | border-color: $base-background-color; 3 | border-style: solid; 4 | border-width: 2px; 5 | display: block; 6 | text-align: center; 7 | 8 | .slats-list & { 9 | border-width: 0 2px 2px 2px; 10 | } 11 | 12 | span, 13 | em, 14 | a { 15 | display: inline-block; 16 | padding: $small-spacing; 17 | 18 | &:not(:last-child) { 19 | border-right: $content-border; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_repo-badge.scss: -------------------------------------------------------------------------------- 1 | .repo-badge { 2 | float: right; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_repo.scss: -------------------------------------------------------------------------------- 1 | .repo-language { 2 | color: $light-font-color; 3 | font-size: $small-font-size; 4 | font-weight: normal; 5 | letter-spacing: 1px; 6 | margin-top: 4px; 7 | text-transform: uppercase; 8 | 9 | @include media(38rem) { 10 | float: right; 11 | } 12 | } 13 | 14 | .repo-badge { 15 | @include media(38rem) { 16 | float: right; 17 | } 18 | } 19 | 20 | .repo-description { 21 | clear: both; 22 | color: $light-font-color; 23 | margin-bottom: 0; 24 | margin-top: $small-spacing / 2; 25 | } 26 | 27 | .repo-instructions { 28 | @include media(43em) { 29 | @include span-columns(6); 30 | } 31 | } 32 | 33 | .repo-action { 34 | text-align: center; 35 | 36 | @include media(43em) { 37 | @include span-columns(6); 38 | margin-right: 0; 39 | } 40 | } 41 | 42 | .stop-triaging { 43 | background-color: $codetriage-red; 44 | 45 | &:hover { 46 | background-color: darken($codetriage-red, 5%); 47 | } 48 | } 49 | 50 | .email-amount { 51 | label { 52 | font-weight: normal; 53 | } 54 | 55 | select { 56 | display: inline-block; 57 | } 58 | 59 | .save-amount { 60 | background: none; 61 | color: $action-color; 62 | display: inline-block; 63 | margin-left: $small-spacing; 64 | padding: 0; 65 | 66 | &:hover { 67 | background: none; 68 | color: $base-font-color; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_section-break.scss: -------------------------------------------------------------------------------- 1 | .section-break { 2 | border-bottom: 5px solid lighten($base-background-color, 5%); 3 | margin: 6rem auto; 4 | max-width: 25rem; 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_staticish-pages.scss: -------------------------------------------------------------------------------- 1 | .static-page { 2 | font-size: $larger-font-size; 3 | 4 | color: $off-white-font-color; 5 | h2 { 6 | color: $base-font-color; 7 | font-size: 2rem; 8 | 9 | padding: 0.5em 0; 10 | margin: 1em 0; 11 | } 12 | .bullets { 13 | padding: 1em 1em 1em 2em; 14 | } 15 | 16 | @import "github/markdown-body"; 17 | } 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_top-bar.scss: -------------------------------------------------------------------------------- 1 | %top-bar { 2 | float: left; 3 | width: 25%; 4 | height: 10px; 5 | display: block; 6 | } 7 | 8 | .top-bar-red { 9 | @extend %top-bar; 10 | background-color: $codetriage-red; 11 | } 12 | 13 | .top-bar-yellow { 14 | @extend %top-bar; 15 | background-color: $codetriage-yellow; 16 | } 17 | 18 | .top-bar-blue { 19 | @extend %top-bar; 20 | background-color: $codetriage-blue; 21 | } 22 | 23 | .top-bar-green { 24 | @extend %top-bar; 25 | background-color: $codetriage-green; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /app/assets/stylesheets/components/_user-email.scss: -------------------------------------------------------------------------------- 1 | .user-email { 2 | margin-top: 7px; 3 | font-weight: normal; 4 | } 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/github/readme.css: -------------------------------------------------------------------------------- 1 | .readme.contributing>div{ 2 | max-height:250px; 3 | overflow:auto 4 | } 5 | .readme .markdown-body,.readme .plain{ 6 | padding:45px; 7 | word-wrap:break-word; 8 | background-color:#fff; 9 | border:1px solid #ddd; 10 | border-bottom-right-radius:3px; 11 | border-bottom-left-radius:3px 12 | } 13 | .readme .plain pre{ 14 | font-size:15px; 15 | white-space:pre-wrap 16 | } 17 | .file .readme .markdown-body{ 18 | padding:45px; 19 | border:0; 20 | border-radius:0 21 | } 22 | .file .readme table[data-table-type="yaml-metadata"]{ 23 | font-size:12px; 24 | line-height:1 25 | } 26 | .file .readme table[data-table-type="yaml-metadata"] table{ 27 | margin:0 28 | } 29 | -------------------------------------------------------------------------------- /app/assets/stylesheets/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | 2 | .application-footer { 3 | margin-bottom: 4rem; 4 | text-align: center; 5 | } 6 | 7 | .footer-action { 8 | margin-bottom: 2rem; 9 | } 10 | 11 | .housekeeping { 12 | margin-bottom: 1rem; 13 | a { 14 | margin: 0 0.5em; 15 | } 16 | } 17 | 18 | .credits-link { 19 | color: $base-font-color; 20 | display: block; 21 | margin-bottom: 1rem; 22 | padding: 1rem; 23 | 24 | &:hover { 25 | color: $codetriage-red; 26 | 27 | transform: translateY(-4px); 28 | transition: all 0.25s ease-out; 29 | -webkit-transform: scale(1.1); 30 | -ms-transform: scale(1.1); 31 | transform: scale(1.1); 32 | 33 | .credits-logo { 34 | fill: $codetriage-red; 35 | } 36 | } 37 | } 38 | 39 | .credits-logo { 40 | @include size(11rem); 41 | display: block; 42 | fill: $base-font-color; 43 | margin: 0 auto; 44 | } 45 | 46 | .credits { 47 | display: flex; 48 | flex-wrap: wrap; 49 | justify-content: center; 50 | } 51 | 52 | .credit-title { 53 | color: $lightest-font-color; 54 | font-size: 1.75rem; 55 | text-align: center; 56 | vertical-align: top; 57 | } 58 | 59 | .heroku-logo { 60 | padding: 1rem; 61 | } 62 | -------------------------------------------------------------------------------- /app/assets/stylesheets/layout/_header.scss: -------------------------------------------------------------------------------- 1 | .application-navigation { 2 | @include clearfix; 3 | } 4 | 5 | .application-logo { 6 | padding-top: 3rem; 7 | text-align: center; 8 | } 9 | 10 | .application-logo-image { 11 | background: asset-data-url("logo.svg"); 12 | background-repeat: no-repeat; 13 | width: 200px; 14 | height: 56px; 15 | margin: 0 auto; 16 | display: block; 17 | } 18 | 19 | .application-navigation-list { 20 | float: right; 21 | } 22 | 23 | .application-navigation-list-item { 24 | float: left; 25 | 26 | a { 27 | background-color: darken($base-background-color, 10%); 28 | color: $lightest-font-color; 29 | display: block; 30 | padding: $small-spacing $base-spacing; 31 | 32 | &:hover { 33 | color: $base-font-color; 34 | background-color: darken($base-background-color, 15%); 35 | } 36 | } 37 | } 38 | 39 | .user-profile-image { 40 | line-height: 1; 41 | max-height: 3rem; 42 | } 43 | -------------------------------------------------------------------------------- /app/assets/stylesheets/layout/_main-application.scss: -------------------------------------------------------------------------------- 1 | .main-application { 2 | padding: $small-spacing; 3 | 4 | @include media(26rem) { 5 | padding: $base-spacing; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/markdown.scss: -------------------------------------------------------------------------------- 1 | @import "github/markdown-body"; 2 | @import "github/readme"; 3 | 4 | .footer { 5 | margin: 0 auto; 6 | 7 | .logo-wrapper { 8 | padding: 3em 3em 1em 3em; 9 | margin: 0 auto; 10 | width: 200px; 11 | height: 56px; 12 | } 13 | 14 | .logo-wrapper img { 15 | width: 100%; 16 | height: 100%; 17 | } 18 | } 19 | 20 | .footer-links { 21 | padding: 1em; 22 | padding-bottom: 2em; 23 | text-align: center; 24 | margin: 0 auto; 25 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; 26 | font-size: 16px; 27 | line-height: 1.5; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /app/assets/stylesheets/pagination.css: -------------------------------------------------------------------------------- 1 | .digg_pagination { 2 | background: white; 3 | cursor: default; 4 | /* self-clearing method: */ 5 | } 6 | 7 | .digg_pagination a, .digg_pagination span, .digg_pagination em { 8 | padding: 0.2em 0.5em; 9 | display: block; 10 | float: left; 11 | margin-right: 1px; 12 | } 13 | 14 | .digg_pagination .disabled { 15 | color: #999999; 16 | border: 1px solid #dddddd; 17 | } 18 | 19 | .digg_pagination .current { 20 | font-style: normal; 21 | font-weight: bold; 22 | background: #2e6ab1; 23 | color: white; 24 | border: 1px solid #2e6ab1; 25 | } 26 | 27 | .digg_pagination a { 28 | text-decoration: none; 29 | color: #105cb6; 30 | border: 1px solid #9aafe5; 31 | } 32 | 33 | .digg_pagination a:hover, .digg_pagination a:focus { 34 | color: #000033; 35 | border-color: #000033; 36 | } 37 | 38 | .digg_pagination .page_info { 39 | background: #2e6ab1; 40 | color: white; 41 | padding: 0.4em 0.6em; 42 | width: 22em; 43 | margin-bottom: 0.3em; 44 | text-align: center; 45 | } 46 | 47 | .digg_pagination .page_info b { 48 | color: #000033; 49 | background: #6aa6ed; 50 | padding: 0.1em 0.25em; 51 | } 52 | 53 | .digg_pagination:after { 54 | content: "."; 55 | display: block; 56 | height: 0; 57 | clear: both; 58 | visibility: hidden; 59 | } 60 | 61 | * html .digg_pagination { 62 | height: 1%; 63 | } 64 | 65 | *:first-child + html .digg_pagination { 66 | overflow: hidden; 67 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/repo_body.scss: -------------------------------------------------------------------------------- 1 | .repo-body strong { 2 | color: #fff; 3 | } 4 | -------------------------------------------------------------------------------- /app/controllers/api_info_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require File.expand_path("../../../lib/sorted_repo_collection", __FILE__) 4 | 5 | class ApiInfoController < RepoBasedController 6 | include ActionView::Helpers::DateHelper 7 | 8 | def show 9 | @repo = find_repo(params) 10 | added_by = @repo.subscribers.where(private: false).order(:created_at).first&.github 11 | count = @repo.subscribers_count 12 | count = 0 if added_by.nil? 13 | 14 | respond_to do |format| 15 | format.json do 16 | render json: { 17 | stars_count: @repo.stars_count, 18 | subscriber_count: count, 19 | added_by_username: added_by, 20 | time_ago: time_ago_in_words(@repo.created_at), 21 | message: "This is an unstable interface, do not use" 22 | }.to_json 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < ActionController::Base 4 | include ActionView::Helpers::NumberHelper 5 | protect_from_forgery 6 | 7 | before_action do 8 | if current_user&.admin? 9 | Rack::MiniProfiler.authorize_request 10 | end 11 | end 12 | 13 | before_action do 14 | if current_user 15 | Raven.user_context email: current_user.email, id: current_user.id, username: current_user.github 16 | end 17 | end 18 | 19 | def set_description(val) 20 | @meta_description = val 21 | end 22 | 23 | def set_title(val) 24 | @meta_title = val 25 | end 26 | 27 | def authenticate_user! 28 | redirect_to user_github_omniauth_authorize_path(origin: request.fullpath) unless user_signed_in? 29 | end 30 | 31 | def after_sign_in_path_for(resource) 32 | request.env["omniauth.origin"] || stored_location_for(resource) || root_path 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/controllers/issue_assignments_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class IssueAssignmentsController < ApplicationController 4 | def create 5 | repo_sub = current_user.repo_subscriptions.find(params[:id]) 6 | SendSingleTriageEmailJob.perform_later(repo_sub.id) 7 | redirect_to repo_path(repo_sub.repo), notice: "You will receive an email with your new issue shortly" 8 | end 9 | 10 | # get "/issue_assignments/:id/users/:user_id/click/:created_at", to: "issue_assignments#click" 11 | def click_issue_redirect 12 | assignment = IssueAssignment.find(params[:id]) 13 | if assignment&.user&.id.to_s == params[:user_id] 14 | assignment.user.record_click! 15 | assignment.update(clicked: true) 16 | assignment.user.update(last_clicked_at: Time.now) 17 | redirect_to assignment.issue.html_url, allow_other_host: true 18 | else 19 | redirect_to :root, message: "Bad url, if this problem persists please open an issue github.com/codetriage/codetriage" 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/controllers/repo_based_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RepoBasedController < ApplicationController 4 | protected 5 | 6 | def name_from_params(options) 7 | [options[:name], options[:format]].compact.join(".") 8 | end 9 | 10 | def find_repo(options, only_active: true) 11 | repo = Repo 12 | repo = repo.active if only_active 13 | repo.find_by_full_name(options[:full_name].downcase) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/repo_subscriptions_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RepoSubscriptionsController < ApplicationController 4 | before_action :authenticate_user! 5 | 6 | def create 7 | @repo_subscription = create_or_update_subscription 8 | if @repo_subscription.save 9 | SendSingleTriageEmailJob.perform_later(@repo_subscription.id) 10 | redirect_to @repo_subscription.repo, notice: I18n.t("repo_subscriptions.subscribed") 11 | else 12 | flash[:error] = "Something went wrong" 13 | redirect_to repo_path(@repo_subscription.try(:repo) || Repo.find(repo_subscription_params[:repo_id])) 14 | end 15 | end 16 | 17 | def destroy 18 | @repo_sub = current_user.repo_subscriptions.find params[:id] 19 | repo = @repo_sub.repo 20 | @repo_sub.destroy 21 | redirect_to repo_path(repo) 22 | end 23 | 24 | def update 25 | @repo_sub = create_or_update_subscription 26 | if @repo_sub.save 27 | flash[:success] = "Preferences updated!" 28 | else 29 | flash[:error] = "Something went wrong" 30 | end 31 | redirect_to repo_path(@repo_sub.repo) 32 | end 33 | 34 | def create_or_update_subscription 35 | repo_sub = current_user.repo_subscriptions.find(params[:id]) if params[:id] 36 | repo_sub ||= current_user.repo_subscriptions.new(repo: Repo.find(repo_subscription_params[:repo_id])) 37 | repo_sub.update(repo_subscription_params) 38 | repo_sub 39 | end 40 | 41 | private 42 | 43 | def repo_subscription_params 44 | params.require(:repo_subscription).permit( 45 | :repo_id, 46 | :email_limit, 47 | :write, 48 | :write_limit, 49 | :read, 50 | :read_limit 51 | ) 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /app/controllers/subscribers_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SubscribersController < RepoBasedController 4 | def show 5 | @repo = find_repo(params) 6 | @subscribers = @repo.users.page(params[:page]).per_page(params[:per_page] || 50) 7 | set_title("Code helpers for #{@repo.full_name} - #{@repo.language}") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/topics_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TopicsController < ApplicationController 4 | TOPICS = ["hacktoberfest".html_safe].freeze 5 | before_action :set_topic 6 | 7 | def show 8 | set_title("Open Source Project Topic: #{@topic}") 9 | set_description("Open source repos labeled #{@topic}") 10 | 11 | label = Label.find_by(name: @topic) 12 | @repos = Repo.with_some_issues 13 | .joins(:repo_labels) 14 | .where(repo_labels: {label_id: label.id}) 15 | .select(:id, :issues_count, :language, :full_name, :name, :description) 16 | 17 | @repos = @repos.order_by_issue_count.page(valid_params[:page]).per_page(valid_params[:per_page] || 50) 18 | end 19 | 20 | private def set_topic 21 | topic_name = valid_params["id"].downcase 22 | @topic = TOPICS.detect { |t| t == topic_name } 23 | 24 | if @topic.blank? 25 | redirect_back fallback_location: root_path, notice: "Invalid topic #{topic_name.inspect} not found in #{TOPICS.map(&:inspect).join(", ")}" 26 | end 27 | end 28 | 29 | private def valid_params 30 | params.permit(:id, :per_page, :page) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/controllers/users/after_signup_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Users::AfterSignupController < ApplicationController 4 | include Wicked::Wizard 5 | 6 | before_action :authenticate_user! 7 | 8 | steps :set_privacy 9 | 10 | def show 11 | @user = current_user 12 | render_wizard 13 | end 14 | 15 | def update 16 | @user = current_user 17 | @user.update(user_params) 18 | render_wizard @user 19 | end 20 | 21 | private 22 | 23 | def user_params 24 | params.require(:user).permit( 25 | :private, 26 | :email, 27 | :password, 28 | :password_confirmation, 29 | :remember_me, 30 | :zip, 31 | :phone_number, 32 | :twitter, 33 | :github, 34 | :github_access_token, 35 | :avatar_url, 36 | :name, 37 | :favorite_languages, 38 | :daily_issue_limit 39 | ) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /app/controllers/users/omniauth_callbacks_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 4 | def github 5 | @user = GitHubAuthenticator.authenticate(request.env["omniauth.auth"], current_user) 6 | if @user.persisted? 7 | flash[:notice] = if @user.valid_email? 8 | I18n.t "devise.omniauth_callbacks.success", kind: "GitHub" 9 | else 10 | I18n.t "devise.omniauth_callbacks.bad_email_success", kind: "GitHub" 11 | end 12 | 13 | sign_in_and_redirect @user, event: :authentication 14 | else 15 | session["devise.github_data"] = request.env["omniauth.auth"].delete("extra") 16 | flash[:error] = no_email_error if request.env["omniauth.auth"].info.email.blank? 17 | if flash[:error].blank? 18 | flash[:notice] = I18n.t "devise.omniauth_callbacks.failure", 19 | kind: "GitHub", reason: "Invalid credentials" 20 | end 21 | redirect_to root_path 22 | end 23 | end 24 | 25 | private 26 | 27 | def no_email_error 28 | msg = "You need a public email address on GitHub to sign up you can add" 29 | msg << " an email, sign up for triage, then remove it from GitHub:
21 | <%= doc.doc_comments.first.try(:comment) %> 22 |23 | 24 | <% end %> 25 | <% end %> 26 | 27 | -- 28 | 29 | Go forth and make the world a better place 30 | 31 | [@HowToOpenSource](https://twitter.com/HowToOpenSource) 32 | [Help doctor more docs at codetriage.com](<%= root_url %>) 33 | -------------------------------------------------------------------------------- /app/views/user_mailer/spam.md.erb: -------------------------------------------------------------------------------- 1 | Hi <%= @user.github %>, 2 | 3 | <%= @message.html_safe %> 4 | 5 | -- 6 | [Richard Schneeman](https://www.schneems.com), creator of CodeTriage 7 | -------------------------------------------------------------------------------- /app/views/users/after_signup/set_privacy.html.slim: -------------------------------------------------------------------------------- 1 | h2 Set Privacy 2 | p By default when you subscribe to a repo to triage, that information will be public knowledge. We think this is a good thing, you're helping out the open source community so why not share the fun? We won't share your email, or anything else, just your GitHub username and the repo you are subscribing to. It might look something like this: 3 | div style='height:50px; border: solid 1px black; display:inline-block; padding: 0 100px 0 0; border-radius: 5px' 4 | => image_tag current_user.avatar_url, class: 'img-rounded', style: "height: 40px; margin: 5px" 5 | | #{current_user.github} has subscribed to: #{link_to "codetriage/codetriage", "https://github.com/codetriage/codetriage"} 6 | p While we think this might be an awesome show of your commitment to quality code, you might not want this info public, if that's the case, we understand. You can make your account private by selecting the appropriate button below: 7 | = link_to "Make Private", next_wizard_path(user: {private: true}), method: :patch, class: "btn btn-primary" 8 | =<> link_to "Stay Public", next_wizard_path(user: {private: false}), method: :patch, class: "btn btn-success" 9 | = link_to "skip →", next_wizard_path, class: "btn btn-primary" 10 | p You can change your mind any time, and set your account to private on your settings page. 11 | -------------------------------------------------------------------------------- /app/views/users/edit.html.slim: -------------------------------------------------------------------------------- 1 | .subpage-content-wrapper 2 | section.subpage-content-header 3 | h1.subpage-primary-title 4 | | Edit 5 | = @user.github 6 | 7 | section.user-settings.content-section 8 | = form_for @user, url: user_path(@user), method: :patch, html: { class: "edit_user", id: "edit_user" } do |f| 9 | = render partial: "form", locals: {f: f} 10 | -------------------------------------------------------------------------------- /app/views/users/token_delete.html.slim: -------------------------------------------------------------------------------- 1 | section.subpage-content-wrapper.high 2 | header.subpage-content-header 3 | h1.subpage-primary-title Delete Account? 4 | p.subpage-secondary-title This cannot be undone. 5 | 6 | .repo-body 7 | - if @lonely_repos.present? 8 | section.help-triage.content-section 9 | | If you delete your account these CodeTriage repos will have no subscribers and will be removed as well. 10 | ul.bullets 11 | - @lonely_repos.each do |repo| 12 | li= link_to repo.full_name, repo_path(repo) 13 | 14 | section.help-triage.content-section 15 | | The only thing this app does is send emails. The only way to unsubscribe is account deletion. If you have feedback for the project, please 16 | = link_to " open up an issue on GitHub", "https://github.com/codetriage/codetriage/issues" 17 | | . 18 | 19 | section.help-triage.content-section 20 | = form_for @user, url: token_delete_user_path(@user.account_delete_token), method: :delete, html_options: { class: "form form-horizontal danger" } do |f| 21 | = link_to "Cancel", root_url, class: "button" 22 | | 23 | | 24 | = f.submit "💀 Delete My Account", class: "btn btn-danger", id: "destroy_user", data: { confirm: 'This cannot be undone, are you sure?' } 25 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/puma: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by Bundler. 4 | # 5 | # The application 'puma' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'pathname' 10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", 11 | Pathname.new(__FILE__).realpath) 12 | 13 | require 'rubygems' 14 | require 'bundler/setup' 15 | 16 | load Gem.bin_path('puma', 'puma') 17 | -------------------------------------------------------------------------------- /bin/pumactl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by Bundler. 4 | # 5 | # The application 'pumactl' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'pathname' 10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", 11 | Pathname.new(__FILE__).realpath) 12 | 13 | require 'rubygems' 14 | require 'bundler/setup' 15 | 16 | load Gem.bin_path('puma', 'pumactl') 17 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies 21 | # system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:setup' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to update your development environment automatically. 13 | # Add necessary update steps to this file. 14 | 15 | puts '== Installing dependencies ==' 16 | system! 'gem install bundler --conservative' 17 | system('bundle check') || system!('bundle install') 18 | 19 | # Install JavaScript dependencies 20 | # system('bin/yarn') 21 | 22 | puts "\n== Updating database ==" 23 | system! 'rails db:migrate' 24 | 25 | puts "\n== Removing old logs and tempfiles ==" 26 | system! 'rails log:clear tmp:clear' 27 | 28 | puts "\n== Restarting application server ==" 29 | system! 'rails restart' 30 | end 31 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | APP_ROOT = File.expand_path('..', __dir__) 5 | Dir.chdir(APP_ROOT) do 6 | executable_path = ENV["PATH"].split(File::PATH_SEPARATOR).find do |path| 7 | normalized_path = File.expand_path(path) 8 | 9 | normalized_path != __dir__ && File.executable?(Pathname.new(normalized_path).join('yarn')) 10 | end 11 | 12 | if executable_path 13 | exec File.expand_path(Pathname.new(executable_path).join('yarn')), *ARGV 14 | else 15 | $stderr.puts "Yarn executable was not detected in the system." 16 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 17 | exit 1 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require "rbtrace" 6 | require_relative "config/environment" 7 | 8 | run Rails.application 9 | Rails.application.load_server 10 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "boot" 4 | 5 | require "rails/all" 6 | 7 | # Require the gems listed in Gemfile, including any gems 8 | # you've limited to :test, :development, or :production. 9 | Bundler.require(*Rails.groups) 10 | 11 | module CodeTriage 12 | class Application < Rails::Application 13 | # Initialize configuration defaults for originally generated Rails version. 14 | config.load_defaults 7.0 15 | 16 | # Settings in config/environments/* take precedence over those specified here. 17 | # Application configuration should go into files in config/initializers 18 | # -- all .rb files in that directory are automatically loaded. 19 | config.active_job.queue_adapter = :sidekiq 20 | config.encoding = "utf-8" 21 | # Enable the asset pipeline 22 | config.assets.enabled = true 23 | config.assets.initialize_on_precompile = false 24 | # Set i18n.enforce_available_locales to true 25 | config.i18n.enforce_available_locales = true 26 | 27 | config.force_ssl = ENV["APPLICATION_HOST"] 28 | config.middleware.insert_after ActionDispatch::SSL, Rack::CanonicalHost, ENV["APPLICATION_HOST"] if ENV["APPLICATION_HOST"] 29 | # Application configuration can go into files in config/initializers 30 | # -- all .rb files in that directory are automatically loaded after loading 31 | # the framework and any gems in your application. 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 4 | 5 | require "bundler/setup" # Set up gems listed in the Gemfile. 6 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 7 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: code_triage_production 11 | -------------------------------------------------------------------------------- /config/database.ci.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | adapter: postgresql 3 | encoding: utf8 4 | pool: 5 5 | host: localhost 6 | password: password 7 | username: postgres 8 | 9 | development: 10 | <<: *defaults 11 | database: triage_development 12 | 13 | test: 14 | <<: *defaults 15 | database: triage_test 16 | -------------------------------------------------------------------------------- /config/database.example.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | adapter: postgresql 3 | encoding: utf8 4 | pool: 5 5 | host: localhost 6 | password: 7 | 8 | development: 9 | <<: *defaults 10 | database: triage_development 11 | 12 | test: 13 | <<: *defaults 14 | database: triage_test 15 | 16 | production: 17 | <<: *defaults 18 | database: triage_production 19 | 20 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative "application" 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # ActiveSupport::Reloader.to_prepare do 6 | # ApplicationController.renderer.defaults.merge!( 7 | # http_host: 'example.org', 8 | # https: false 9 | # ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = "1.0" 7 | 8 | # Add additional assets to the asset load path. 9 | # Rails.application.config.assets.paths << Emoji.images_path 10 | # Add Yarn node_modules folder to the asset load path. 11 | Rails.application.config.assets.paths << Rails.root.join("node_modules") 12 | 13 | # Precompile additional assets. 14 | # application.js, application.css, and all non-JS/CSS in the app/assets 15 | # folder are already added. 16 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 17 | -------------------------------------------------------------------------------- /config/initializers/backlog.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Thread.new do 4 | # while 1 do 5 | # sleep 5 6 | 7 | # puts "backlog: " + `netstat -nap tcp | grep $PORT| wc -l` if ENV['PORT'] 8 | # end 9 | # end 10 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 6 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } 7 | 8 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code 9 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". 10 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] 11 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Define an application-wide content security policy 6 | # For further information see the following documentation 7 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 8 | 9 | # Rails.application.config.content_security_policy do |policy| 10 | # policy.default_src :self, :https 11 | # policy.font_src :self, :https, :data 12 | # policy.img_src :self, :https, :data 13 | # policy.object_src :none 14 | # policy.script_src :self, :https 15 | # policy.style_src :self, :https 16 | # # If you are using webpack-dev-server then specify webpack-dev-server host 17 | # policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? 18 | 19 | # # Specify URI for violation reports 20 | # # policy.report_uri "/csp-violation-report-endpoint" 21 | # end 22 | 23 | # If you are using UJS then enable automatic nonce generation 24 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 25 | 26 | # Set the nonce only to specific directives 27 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 28 | 29 | # Report CSP violations to a specified URI 30 | # For further information see the following documentation: 31 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 32 | # Rails.application.config.content_security_policy_report_only = true 33 | -------------------------------------------------------------------------------- /config/initializers/cookie_rotator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.config.after_initialize do 4 | Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| 5 | salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt 6 | secret_key_base = Rails.application.secret_key_base 7 | 8 | key_generator = ActiveSupport::KeyGenerator.new( 9 | secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 10 | ) 11 | key_len = ActiveSupport::MessageEncryptor.key_len 12 | secret = key_generator.generate_key(salt, key_len) 13 | 14 | cookies.rotate :encrypted, secret 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Specify a serializer for the signed and encrypted cookie jars. 6 | # Valid options are :json, :marshal, and :hybrid. 7 | Rails.application.config.action_dispatch.cookies_serializer = :hybrid 8 | -------------------------------------------------------------------------------- /config/initializers/cors.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Avoid CORS issues when API is called from the frontend app. 6 | # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. 7 | 8 | # Read more: https://github.com/cyu/rack-cors 9 | 10 | # Rails.application.config.middleware.insert_before 0, Rack::Cors do 11 | # allow do 12 | # origins 'example.com' 13 | # 14 | # resource '*', 15 | # headers: :any, 16 | # methods: [:get, :post, :put, :patch, :delete, :options, :head] 17 | # end 18 | # end 19 | -------------------------------------------------------------------------------- /config/initializers/covid.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Here is how to add a "COVID-19" related resource to the project 4 | # 5 | # 1) Find the GitHub url of the project such as `https://github.com/nextstrain/ncov` 6 | # 2) Ensure the project is added to CodeTriage, visit https://www.codetriage.com/repos/new and add the repo 7 | # 3) Come back to this file on GitHub and in the COVID_REPOS array (inside the %W{}) add the username and name of the repo 8 | # 4) Save the file in the UI and submit a PR 9 | # 5) Repeat 10 | # 11 | COVID_REPOS = %W[ 12 | nextstrain/ncov 13 | jcl5m1/ventilator 14 | CSSEGISandData/COVID-19 15 | nextstrain/auspice 16 | nextstrain/augur 17 | nextstrain/cli 18 | nextstrain/fauna 19 | nextstrain/nextstrain.org 20 | neherlab/covid19_scenarios 21 | neherlab/covid19_scenarios 22 | mhdhejazi/CoronaTracker 23 | ahmadawais/corona-cli 24 | ushahidi/platform 25 | ushahidi/ushahidi_web 26 | HospitalRun/hospitalrun 27 | HospitalRun/hospitalrun-frontend 28 | HospitalRun/hospitalrun-server 29 | learningequality/kolibri 30 | svs/covid19-supply-chain 31 | nytimes/covid-19-data 32 | Leo1690/BtPedalClient 33 | Leo1690/BtPedalServer 34 | covid19india/covid19india-react 35 | ] 36 | -------------------------------------------------------------------------------- /config/initializers/feature_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Define an application-wide HTTP feature policy. For further 3 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 4 | # 5 | # Rails.application.config.feature_policy do |f| 6 | # f.camera :none 7 | # f.gyroscope :none 8 | # f.microphone :none 9 | # f.usb :none 10 | # f.fullscreen :self 11 | # f.payment :self, "https://secure.example.com" 12 | # end 13 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure sensitive parameters which will be filtered from the log file. 6 | Rails.application.config.filter_parameters += [:password] 7 | -------------------------------------------------------------------------------- /config/initializers/git_hub_bub.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # I know it's awful but I don't have time to fix the GitHubBub API and this makes `rails c` not noisey 4 | GitHubBub::Request.send(:remove_const, :GITHUB_VERSION) 5 | GitHubBub::Request.send(:remove_const, :USER_AGENT) 6 | GitHubBub::Request.send(:remove_const, :RETRIES) 7 | 8 | GitHubBub::Request::GITHUB_VERSION = "vnd.github.v3.full+json" 9 | GitHubBub::Request::USER_AGENT = "codetriage" 10 | GitHubBub::Request::RETRIES = 3 11 | 12 | class CodeTraigeRandomApiKeyStore 13 | def initialize 14 | @keys = [] 15 | @mutex = Mutex.new 16 | end 17 | 18 | def call 19 | return ENV["GITHUB_API_KEY"] if ENV["GITHUB_API_KEY"] 20 | 21 | until (key = @keys.pop) 22 | populate_keys 23 | end 24 | 25 | key 26 | end 27 | 28 | private def get_key 29 | @keys.pop 30 | end 31 | 32 | private def populate_keys 33 | @mutex.synchronize do 34 | return if @keys.any? 35 | 36 | @keys = User.fast_rand.where.not(token: nil).limit(5000).pluck(:token) 37 | 38 | if @keys.empty? && User.where.not(token: nil).empty? 39 | raise "No users with tokens in the database" 40 | end 41 | end 42 | end 43 | end 44 | 45 | code_triage_random_api_key_store = CodeTraigeRandomApiKeyStore.new 46 | 47 | # Auth all non authed requests (due to github request limits) 48 | GitHubBub::Request.set_before_callback do |request| 49 | if request.token? 50 | # Request is authorized, do nothing 51 | else 52 | request.token = code_triage_random_api_key_store.call 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new inflection rules using the following format. Inflections 6 | # are locale specific, and you may define rules for as many different 7 | # locales as you wish. All of these examples are active by default: 8 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 9 | # inflect.plural /^(ox)$/i, '\1en' 10 | # inflect.singular /^(ox)en/i, '\1' 11 | # inflect.irregular 'person', 'people' 12 | # inflect.uncountable %w( fish sheep ) 13 | # end 14 | 15 | # These inflection rules are supported but not enabled by default: 16 | ActiveSupport::Inflector.inflections(:en) do |inflect| 17 | inflect.acronym "PHP" 18 | end 19 | -------------------------------------------------------------------------------- /config/initializers/mail.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ActionMailer::Base.smtp_settings = { 4 | address: "smtp.sendgrid.net", 5 | port: "587", 6 | authentication: :plain, 7 | user_name: ENV["SENDGRID_USERNAME"], 8 | password: ENV["SENDGRID_PASSWORD"], 9 | domain: "codetriage.com" 10 | } 11 | ActionMailer::Base.delivery_method ||= :smtp 12 | 13 | Maildown.allow_indentation = true 14 | Premailer::Rails.config[:generate_text_part] = false 15 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new mime types for use in respond_to blocks: 6 | # Mime::Type.register "text/richtext", :rtf 7 | 8 | Mime::Type.register "image/svg+xml", :svg 9 | -------------------------------------------------------------------------------- /config/initializers/mini-profiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # set RedisStore so Rack Mini-Profiler works with multiple servers 4 | if Rails.env.production? && ENV["REDIS_URL"] 5 | uri = URI.parse(ENV["REDIS_URL"]) 6 | Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore 7 | Rack::MiniProfiler.config.storage_options = {host: uri.host, port: uri.port, password: uri.password} 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | # 5 | # This file contains migration options to ease your Rails 5.0 upgrade. 6 | # 7 | # Once upgraded flip defaults one by one to migrate to the new default. 8 | # 9 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 10 | 11 | # Enable per-form CSRF tokens. Next major version defaults to true. 12 | Rails.application.config.action_controller.per_form_csrf_tokens = true 13 | 14 | # Enable origin-checking CSRF mitigation. Next major version defaults to true. 15 | Rails.application.config.action_controller.forgery_protection_origin_check = true 16 | 17 | # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. 18 | ActiveSupport.to_time_preserves_timezone = true 19 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Define an application-wide HTTP permissions policy. For further 4 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 5 | # 6 | # Rails.application.config.permissions_policy do |f| 7 | # f.camera :none 8 | # f.gyroscope :none 9 | # f.microphone :none 10 | # f.usb :none 11 | # f.fullscreen :self 12 | # f.payment :self, "https://secure.example.com" 13 | # end 14 | -------------------------------------------------------------------------------- /config/initializers/puma_worker_killer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # PumaAutoTune.start 4 | -------------------------------------------------------------------------------- /config/initializers/request_forgery_protection.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Enable origin-checking CSRF mitigation. 6 | Rails.application.config.action_controller.forgery_protection_origin_check = true 7 | -------------------------------------------------------------------------------- /config/initializers/sentry.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Raven.configure do |config| 4 | config.excluded_exceptions += ["Sidekiq::Shutdown"] 5 | 6 | config.async = lambda do |event| 7 | Thread.new do 8 | Raven.send_event(event) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | Rails.application.config.session_store :cookie_store, key: "_code_triage_session" 6 | -------------------------------------------------------------------------------- /config/initializers/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Sidekiq.default_configuration.redis = { 4 | url: ENV["REDIS_URL"], 5 | ssl_params: { 6 | verify_mode: OpenSSL::SSL::VERIFY_NONE 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /config/initializers/silence_warnings.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/config/initializers/silence_warnings.rb -------------------------------------------------------------------------------- /config/initializers/the_lone_dyno.rb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /config/initializers/time_formats.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Time::DATE_FORMATS[:time_only_with_zone] = "%H:%M %Z" 4 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # This file contains settings for ActionController::ParamsWrapper which 6 | # is enabled by default. 7 | 8 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 9 | ActiveSupport.on_load(:action_controller) do 10 | wrap_parameters format: [:json] 11 | end 12 | 13 | # To enable root element in JSON for ActiveRecord objects. 14 | # ActiveSupport.on_load(:active_record) do 15 | # self.include_root_in_json = true 16 | # end 17 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at http://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | repo_subscriptions: 34 | subscribed: "Awesome! You'll receive daily triage e-mails for this repository." 35 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Puma can serve each request in a thread from an internal thread pool. 4 | # The `threads` method setting takes two numbers: a minimum and maximum. 5 | # Any libraries that use thread pools should be configured to match 6 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 7 | # and maximum; this matches the default thread size of Active Record. 8 | # 9 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 10 | threads threads_count, threads_count 11 | 12 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 13 | # 14 | port ENV.fetch("PORT") { 3000 } 15 | 16 | # Allow puma to be restarted by `rails restart` command. 17 | plugin :tmp_restart 18 | 19 | before_fork do 20 | require "puma_worker_killer" 21 | 22 | PumaWorkerKiller.enable_rolling_restart # Default is every 6 hours 23 | end 24 | 25 | # on_worker_boot do 26 | # Barnes.start 27 | # end 28 | -------------------------------------------------------------------------------- /config/scout_apm.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | name: codetriage 3 | key: <%= ENV['SCOUT_KEY'] %> 4 | monitor: <%= true if ENV['SCOUT_MONITOR'] %> 5 | 6 | development: 7 | <<: *defaults 8 | test: 9 | <<: *defaults 10 | production: 11 | <<: *defaults 12 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rails secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 8a251689fe2c9dbbc9bae32031162df989752e2e178b745d1a2f90c1979272e5fbb38e5b43fb5629a40ede0b3fd8958b3bc8a13a38b332356b0974a3a8c843d2 15 | 16 | test: 17 | secret_key_base: 7ec058f05fe649308e5e566086efc18f11130f8196da8a64567347aa812d28a62be55b4dedd140aa7e086619dd7e40a85eb3b0ebc5c26e1483f17d8fd931e7a5 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /db/migrate/20120222223509_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table(:users) do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Recoverable 9 | t.string :reset_password_token 10 | t.datetime :reset_password_sent_at 11 | 12 | ## Rememberable 13 | t.datetime :remember_created_at 14 | 15 | ## Trackable 16 | t.integer :sign_in_count, default: 0 17 | t.datetime :current_sign_in_at 18 | t.datetime :last_sign_in_at 19 | t.string :current_sign_in_ip 20 | t.string :last_sign_in_ip 21 | 22 | ## Encryptable 23 | # t.string :password_salt 24 | 25 | ## Confirmable 26 | # t.string :confirmation_token 27 | # t.datetime :confirmed_at 28 | # t.datetime :confirmation_sent_at 29 | # t.string :unconfirmed_email # Only if using reconfirmable 30 | 31 | ## Lockable 32 | # t.integer :failed_attempts, default: 0 # Only if lock strategy is :failed_attempts 33 | # t.string :unlock_token # Only if unlock strategy is :email or :both 34 | # t.datetime :locked_at 35 | 36 | ## Token authenticatable 37 | # t.string :authentication_token 38 | 39 | t.timestamps 40 | end 41 | 42 | add_index :users, :email, unique: true 43 | add_index :users, :reset_password_token, unique: true 44 | # add_index :users, :confirmation_token, unique: true 45 | # add_index :users, :unlock_token, unique: true 46 | # add_index :users, :authentication_token, unique: true 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /db/migrate/20120222231841_user_data.rb: -------------------------------------------------------------------------------- 1 | class UserData < ActiveRecord::Migration[4.2] 2 | def up 3 | add_column :users, :zip, :string 4 | add_column :users, :phone_number, :string 5 | add_column :users, :twitter, :boolean 6 | end 7 | 8 | def down 9 | remove_column :users, :phone_number 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20120518083745_create_issues.rb: -------------------------------------------------------------------------------- 1 | class CreateIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :issues do |t| 4 | t.integer :comment_count 5 | t.string :url, :repo_name, :user_name 6 | t.datetime :last_touched_at 7 | t.integer :number 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20120518085406_create_repo_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class CreateRepoSubscriptions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :repo_subscriptions do |t| 4 | t.string :user_name 5 | t.string :repo_name 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20120518090213_create_issue_assignments.rb: -------------------------------------------------------------------------------- 1 | class CreateIssueAssignments < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :issue_assignments do |t| 4 | t.integer :user_id 5 | t.integer :issue_id 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20120518091140_create_repos.rb: -------------------------------------------------------------------------------- 1 | class CreateRepos < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :repos do |t| 4 | t.string "name" 5 | t.string "user_name" 6 | t.integer "issues_count", default: 0, null: false 7 | t.string "language" 8 | t.string "description" 9 | t.string "full_name" 10 | t.text "notes" 11 | 12 | t.timestamps 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20120620000230_add_github_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddGithubToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :github, :string 4 | add_column :users, :github_access_token, :string 5 | add_index :users, :github, unique: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20120622203236_add_repos_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddReposToIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issues, :repo_id, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120622233057_issue_titles.rb: -------------------------------------------------------------------------------- 1 | class IssueTitles < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issues, :title, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120622235822_add_user_and_repo_to_repo_subscription.rb: -------------------------------------------------------------------------------- 1 | class AddUserAndRepoToRepoSubscription < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repo_subscriptions, :user_id, :integer 4 | add_column :repo_subscriptions, :repo_id, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20120624204958_add_last_sent_at_to_repo_sub.rb: -------------------------------------------------------------------------------- 1 | class AddLastSentAtToRepoSub < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repo_subscriptions, :last_sent_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120624212352_add_html_url_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddHtmlUrlToIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issues, :html_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120624213335_add_status_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddStatusToIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issues, :state, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120627213051_add_repo_sub_to_issue_assignment.rb: -------------------------------------------------------------------------------- 1 | class AddRepoSubToIssueAssignment < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issue_assignments, :repo_subscription_id, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20120707182259_add_admin_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddAdminToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :admin, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20121106072214_repo_issue_counter_cache.rb: -------------------------------------------------------------------------------- 1 | class RepoIssueCounterCache < ActiveRecord::Migration[4.2] 2 | def up 3 | unless column_exists?(:repos, :issues_count) 4 | add_column :repos, :issues_count, :integer, default: 0, null: false 5 | end 6 | 7 | Repo.reset_column_information 8 | Repo.find_each do |repo| 9 | Repo.update_counters(repo.id, issues_count: repo.issues.where(state: "open").count) 10 | end 11 | end 12 | 13 | def down 14 | remove_column :repos, :issues_count 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20121110213717_add_avatar_url_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddAvatarUrlToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :avatar_url, :string, default: "http://gravatar.com/avatar/default" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20121112100015_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNameToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20121120203919_add_language_and_description_to_repo.rb: -------------------------------------------------------------------------------- 1 | class AddLanguageAndDescriptionToRepo < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repos, :language, :string unless column_exists?(:repos, :language) 4 | add_column :repos, :description, :string unless column_exists?(:repos, :description) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20121127163516_add_privacy_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddPrivacyToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :private, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20121127171308_add_full_name_to_repos.rb: -------------------------------------------------------------------------------- 1 | class AddFullNameToRepos < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repos, :full_name, :string unless column_exists?(:repos, :full_name) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20121128162942_add_notes_to_repo.rb: -------------------------------------------------------------------------------- 1 | class AddNotesToRepo < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repos, :notes, :text unless column_exists?(:repos, :notes) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20130222201747_add_favorite_languages_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddFavoriteLanguagesToUser < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :favorite_languages, :string, array: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20130312023533_add_email_limit_to_repo_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddEmailLimitToRepoSubscriptions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repo_subscriptions, :email_limit, :integer, default: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20130503183402_add_daily_issue_limit_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddDailyIssueLimitToUser < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :daily_issue_limit, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20130803144944_update_private_attribute_of_user.rb: -------------------------------------------------------------------------------- 1 | class UpdatePrivateAttributeOfUser < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :users, :private, :boolean, default: false 4 | # Update existing users. Set :private to false if it is nil 5 | User.where(private: nil).find_each do |u| 6 | u.private = false 7 | u.save! 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20130918055659_add_pr_attached_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddPrAttachedToIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issues, :pr_attached, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20130918060600_add_skip_issues_with_pr_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddSkipIssuesWithPrToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :skip_issues_with_pr, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131107042958_add_delete_token_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddDeleteTokenToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :account_delete_token, :string 4 | add_index :users, :account_delete_token 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20140524120051_add_click_to_issue_assignment.rb: -------------------------------------------------------------------------------- 1 | class AddClickToIssueAssignment < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issue_assignments, :clicked, :boolean, default: false 4 | add_column :users, :last_clicked_at, :timestamp 5 | User.find_each(&:save) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140621155109_add_delievered_to_issue_assignment.rb: -------------------------------------------------------------------------------- 1 | class AddDelieveredToIssueAssignment < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :issue_assignments, :delivered, :boolean, {default: false} 4 | # add_index :users, :github, unique: true 5 | add_index :issue_assignments, :delivered 6 | 7 | ::IssueAssignment.find_each do |assignment| 8 | assignment.delivered = true if assignment.respond_to?(:delivered) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20140710161559_store_github_request_errors.rb: -------------------------------------------------------------------------------- 1 | class StoreGithubRequestErrors < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :repos, :github_error_msg, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140710164307_remove_user_id_from_issue_assignments.rb: -------------------------------------------------------------------------------- 1 | class RemoveUserIdFromIssueAssignments < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :issue_assignments, :user_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150629002651_remove_repo_name_from_repo_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class RemoveRepoNameFromRepoSubscriptions < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :repo_subscriptions, :repo_name 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150629010617_remove_user_name_from_repo_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class RemoveUserNameFromRepoSubscriptions < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :repo_subscriptions, :user_name 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20151007212330_create_data_dumps.rb: -------------------------------------------------------------------------------- 1 | class CreateDataDumps < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :data_dumps do |t| 4 | t.text :data 5 | t.timestamps 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20151021160718_add_index_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToIssues < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :issues, :state 4 | add_index :issues, :number 5 | add_index :issues, :repo_id 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20151214120117_enable_pg_stat_extension.rb: -------------------------------------------------------------------------------- 1 | class EnablePgStatExtension < ActiveRecord::Migration[4.2] 2 | def change 3 | execute <<-SQL 4 | CREATE extension IF NOT EXISTS "pg_stat_statements" 5 | SQL 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20160404140129_add_click_to_doc_assignments.rb: -------------------------------------------------------------------------------- 1 | class AddClickToDocAssignments < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :doc_assignments, :clicked, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160404173429_remove_user_from_doc_assignments.rb: -------------------------------------------------------------------------------- 1 | class RemoveUserFromDocAssignments < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :doc_assignments, :user_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160606060546_add_email_frequency_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddEmailFrequencyToUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :users, :email_frequency, :string, default: "daily" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160613220116_change_issues_title_to_text.rb: -------------------------------------------------------------------------------- 1 | class ChangeIssuesTitleToText < ActiveRecord::Migration[5.0] 2 | def up 3 | change_column :issues, :title, :text 4 | end 5 | 6 | def down 7 | change_column :issues, :title, :string, limit: 255 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20160827023209_add_stars_count_to_repos.rb: -------------------------------------------------------------------------------- 1 | class AddStarsCountToRepos < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :repos, :stars_count, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160827073041_update_stars_count_of_repos.rb: -------------------------------------------------------------------------------- 1 | class UpdateStarsCountOfRepos < ActiveRecord::Migration[5.0] 2 | def change 3 | Repo.where(stars_count: nil).find_each do |repo| 4 | repo_path = File.join "repos", "#{repo.user_name}/#{repo.name}" 5 | resp = GitHubBub.get(repo_path).json_body 6 | repo.stars_count = resp["stargazers_count"] 7 | repo.save! 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20160927195642_add_index_to_repo_subscription_id.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToRepoSubscriptionId < ActiveRecord::Migration[5.0] 2 | def change 3 | add_index :issue_assignments, :repo_subscription_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170203143323_add_email_time_of_day_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddEmailTimeOfDayToUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :users, :email_time_of_day, :time 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170516193426_repos_name_index.rb: -------------------------------------------------------------------------------- 1 | class ReposNameIndex < ActiveRecord::Migration[5.0] 2 | def change 3 | add_index :repos, :user_name 4 | add_index :repos, :name 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170523195422_add_language_index.rb: -------------------------------------------------------------------------------- 1 | class AddLanguageIndex < ActiveRecord::Migration[5.0] 2 | def change 3 | add_index :repos, :language 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170604190958_add_old_token_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddOldTokenToUsers < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :users, :old_token, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170619152237_add_index_to_issues_count.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToIssuesCount < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index :repos, :issues_count 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170622201545_add_created_at_index_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddCreatedAtIndexToIssues < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index :issues, :created_at, where: "state = '#{Issue::OPEN}'" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170626162701_make_multi_index.rb: -------------------------------------------------------------------------------- 1 | class MakeMultiIndex < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_index(:issues, :created_at) if index_exists?(:issues, :created_at) 4 | add_index(:issues, [:repo_id, :created_at], where: "state = '#{Issue::OPEN}'") 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170627024417_add_index_to_doc_method.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToDocMethod < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:doc_methods, [:repo_id, :created_at]) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170629151616_add_unique_index_to_repos.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToRepos < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index :repos, [:name, :user_name], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170629230855_index_full_name_of_repos.rb: -------------------------------------------------------------------------------- 1 | class IndexFullNameOfRepos < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:repos, [:full_name]) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170629233102_add_foreign_key_to_repo_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddForeignKeyToRepoSubscriptions < ActiveRecord::Migration[5.1] 2 | def change 3 | add_foreign_key :repo_subscriptions, :repos 4 | add_index(:repo_subscriptions, :repo_id) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170630002100_add_foreign_key_for_repo_users.rb: -------------------------------------------------------------------------------- 1 | class AddForeignKeyForRepoUsers < ActiveRecord::Migration[5.1] 2 | def change 3 | add_foreign_key :repo_subscriptions, :users 4 | add_index(:repo_subscriptions, :user_id) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170630191148_add_index_to_issue_on_repo_id_and_number.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToIssueOnRepoIdAndNumber < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:issues, [:repo_id, :number]) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170630192013_add_index_to_doc_method_creation.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToDocMethodCreation < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:doc_methods, [:repo_id, :name, :path]) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170801021151_default_value_for_max_issues.rb: -------------------------------------------------------------------------------- 1 | class DefaultValueForMaxIssues < ActiveRecord::Migration[5.1] 2 | def change 3 | change_column_default :users, :daily_issue_limit, 50 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171125012313_add_partial_index_to_id.rb: -------------------------------------------------------------------------------- 1 | class AddPartialIndexToId < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:issues, :id, where: "state = '#{Issue::OPEN}'") 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171125013100_remove_partial_index_to_id.rb: -------------------------------------------------------------------------------- 1 | class RemovePartialIndexToId < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_index(:issues, name: "index_issues_on_repo_id_and_created_at") 4 | remove_index(:issues, name: "index_issues_on_id") 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20171125013319_add_index_for_pagination.rb: -------------------------------------------------------------------------------- 1 | class AddIndexForPagination < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index(:issues, [:repo_id, :id], where: "state = '#{Issue::OPEN}'") 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171125202301_fix_doc_methods_indexes.rb: -------------------------------------------------------------------------------- 1 | class FixDocMethodsIndexes < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_index(:doc_methods, name: "index_doc_methods_on_repo_id_and_created_at") 4 | add_index(:doc_methods, [:repo_id, :id]) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20171125212307_add_subscribers_count_to_repos.rb: -------------------------------------------------------------------------------- 1 | class AddSubscribersCountToRepos < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :repos, :subscribers_count, :integer, default: 0 4 | Repo.reset_column_information 5 | Repo.find_each do |p| 6 | Repo.reset_counters p.id, :subscribers_count 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20180716144937_add_streak_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddStreakToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :raw_streak_count, :integer, default: 0 4 | add_column :users, :raw_emails_since_click, :integer, default: 0 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180820155654_add_last_email_at_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddLastEmailAtToUser < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :last_email_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190322102229_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20180723000244) 2 | class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0] 3 | def up 4 | return if foreign_key_exists?(:active_storage_attachments, column: :blob_id) 5 | 6 | if table_exists?(:active_storage_blobs) 7 | add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20191010023214_add_docs_subscriber_count_to_repos.rb: -------------------------------------------------------------------------------- 1 | class AddDocsSubscriberCountToRepos < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :repos, :docs_subscriber_count, :integer, default: 0 4 | add_index :repo_subscriptions, :read 5 | add_index :repo_subscriptions, :write 6 | add_index :repo_subscriptions, :repo_id 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20191014201819_drop_unused_indexes.rb: -------------------------------------------------------------------------------- 1 | class DropUnusedIndexes < ActiveRecord::Migration[6.0] 2 | def change 3 | # public.issues | index_issues_on_number | 198 MB | 0 4 | # public.issues | index_issues_on_repo_id | 1536 MB | 0 5 | # public.issue_assignments | index_issue_assignments_on_repo_subscription_id_and_created_at | 370 MB | 0 6 | remove_index(:issues, name: "index_issues_on_number") 7 | remove_index(:issues, name: "index_issues_on_repo_id") 8 | remove_index(:issue_assignments, name: "index_issue_assignments_on_repo_subscription_id_and_created_at") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20191017202913_add_removed_from_github_to_repo.rb: -------------------------------------------------------------------------------- 1 | class AddRemovedFromGithubToRepo < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :repos, :removed_from_github, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191025030201_add_unique_index_number_repo_id.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexNumberRepoId < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :issues, [:number, :repo_id], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191025191255_add_updated_at_index_to_issues.rb: -------------------------------------------------------------------------------- 1 | class AddUpdatedAtIndexToIssues < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :issues, :updated_at, where: "state = '#{Issue::OPEN}'" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191029194525_make_timestamps_not_nullable.rb: -------------------------------------------------------------------------------- 1 | class MakeTimestampsNotNullable < ActiveRecord::Migration[6.0] 2 | def change 3 | %W[issues repos users doc_methods doc_classes repos repo_subscriptions issue_assignments].each do |table_name| 4 | change_column_null table_name, :created_at, false, "NOW()" 5 | change_column_null table_name, :updated_at, false, "NOW()" 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20191031142027_add_comment_to_doc_method.rb: -------------------------------------------------------------------------------- 1 | class AddCommentToDocMethod < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :doc_methods, :has_comment, :boolean, index: true 4 | add_column :doc_methods, :comment, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20191031144636_add_unique_indexes_to_doc_methods.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexesToDocMethods < ActiveRecord::Migration[6.0] 2 | disable_ddl_transaction! 3 | 4 | def change 5 | remove_index :doc_methods, [:repo_id, :name, :path] 6 | add_index :doc_methods, [:repo_id, :name, :path], unique: true, algorithm: :concurrently 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20201115123024_add_service_name_to_active_storage_blobs.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20190112182829) 2 | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] 3 | def up 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | unless column_exists?(:active_storage_blobs, :service_name) 7 | add_column :active_storage_blobs, :service_name, :string 8 | 9 | configured_service = ActiveStorage::Blob.service.name 10 | if configured_service 11 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) 12 | end 13 | 14 | change_column :active_storage_blobs, :service_name, :string, null: false 15 | end 16 | end 17 | 18 | def down 19 | remove_column :active_storage_blobs, :service_name 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /db/migrate/20201115123025_create_active_storage_variant_records.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20191206030411) 2 | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] 3 | def change 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | create_table :active_storage_variant_records do |t| 7 | t.belongs_to :blob, null: false, index: false 8 | t.string :variation_digest, null: false 9 | 10 | t.index %i[blob_id variation_digest], name: "index_active_storage_variant_records_uniqueness", unique: true 11 | t.foreign_key :active_storage_blobs, column: :blob_id 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20220908011235_add_htos_promo_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddHtosPromoToUser < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :users, :htos_contributor_unsubscribe, :boolean, default: false, null: false 4 | add_column :users, :htos_contributor_bought, :boolean, default: false, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20221004010742_create_labels_table.rb: -------------------------------------------------------------------------------- 1 | class CreateLabelsTable < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :labels do |t| 4 | t.string :name, null: false 5 | 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20221004010749_create_repo_labels_table.rb: -------------------------------------------------------------------------------- 1 | class CreateRepoLabelsTable < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :repo_labels do |t| 4 | t.references :repo, foreign_key: true, null: false 5 | t.references :label, foreign_key: true, null: false 6 | 7 | t.timestamps 8 | end 9 | 10 | add_index :repo_labels, [:repo_id, :label_id], unique: true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20221010011048_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20211119233751) 2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] 3 | def change 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | change_column_null(:active_storage_blobs, :checksum, true) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20221013212959_add_archived_column_to_repo.rb: -------------------------------------------------------------------------------- 1 | class AddArchivedColumnToRepo < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :repos, :archived, :boolean, default: false 4 | add_index :repos, :archived 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20221228065556_add_index_subscriber_count.rb: -------------------------------------------------------------------------------- 1 | class AddIndexSubscriberCount < ActiveRecord::Migration[7.0] 2 | def change 3 | add_index :repos, :subscribers_count 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /doc/README_FOR_APP: -------------------------------------------------------------------------------- 1 | Use this README file to introduce your application and point to useful places in the API for learning more. 2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. 3 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | buildpacks: 3 | - heroku/metrics 4 | - https://github.com/mojodna/heroku-buildpack-jemalloc.git#v3.6.0 5 | - heroku/nodejs 6 | - heroku/ruby 7 | -------------------------------------------------------------------------------- /lib/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/lib/assets/.gitkeep -------------------------------------------------------------------------------- /lib/dependency_parser/php/parse.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module DependencyParser 6 | module PHP 7 | class Parse 8 | attr_reader :errors 9 | 10 | def initialize(content) 11 | @content = content 12 | @errors = [] 13 | @direct = [] 14 | end 15 | 16 | def call 17 | deps = JSON.parse(content, symbolize_names: true) 18 | @direct = deps[:packages].map do |package| 19 | {name: package[:name], url: package.dig(:source, :url), description: package[:description]} 20 | end 21 | @direct += deps[:"packages-dev"].map do |package| 22 | {name: package[:name], url: package.dig(:source, :url), description: package[:description]} 23 | end 24 | rescue 25 | @errors << "Cannot parse lock file" 26 | end 27 | 28 | def direct 29 | {repos: @direct, language: "php"} 30 | end 31 | 32 | def success? 33 | errors.empty? 34 | end 35 | 36 | def error? 37 | errors.any? 38 | end 39 | 40 | private 41 | 42 | attr_reader :content 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/docs_doctor/doc_obj.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/lib/docs_doctor/doc_obj.rb -------------------------------------------------------------------------------- /lib/docs_doctor/loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # loads parsers for different languages and tools 4 | module DocsDoctor 5 | class Loader 6 | attr_accessor :name, :version, :lang 7 | 8 | def initialize(parser_lang_name, version) 9 | @lang, @name = parser_lang_name.to_s.downcase.split("/") 10 | @version = Gem::Version.new version 11 | load_parser 12 | end 13 | 14 | def parser 15 | require path 16 | constant.new 17 | end 18 | 19 | def constant 20 | Kernel.const_get "DocsDoctor::Parsers::#{lang.capitalize}::#{name.capitalize}_#{pretty_version}" 21 | end 22 | 23 | # parsers/ruby/rdoc.rb 24 | def path 25 | [__dir__, "parsers", lang, name_extension].join("/") 26 | end 27 | 28 | def load_parser 29 | case lang 30 | when "ruby" 31 | Ruby.new(name, version).load 32 | else 33 | raise "looks like parser for language #{lang} is not yet implemented" 34 | end 35 | end 36 | 37 | private 38 | 39 | def name_extension 40 | name + dot_extension 41 | end 42 | 43 | def dot_extension 44 | @extension = extension 45 | @extension.prepend(".rb") unless @extension.include?(".") 46 | @extension 47 | end 48 | 49 | def pretty_version 50 | version.to_s.tr(".", "_") 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/docs_doctor/parser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DocsDoctor 4 | class Parser 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/docs_doctor/parsers/ruby/require 'atomic': -------------------------------------------------------------------------------- 1 | require 'atomic' 2 | 3 | array = Atomic.new([]) 4 | 5 | threads = [] 6 | def insert_into_array(array, value, threads) 7 | threads << Thread.new do 8 | array.update{|v| 9 | puts "== Running Update" 10 | v << value 11 | } 12 | end 13 | end 14 | 15 | 16 | insert_into_array(array, 1, threads) 17 | insert_into_array(array, 2, threads) 18 | insert_into_array(array, 3, threads) 19 | 20 | threads.map(&:join) 21 | 22 | puts array.value -------------------------------------------------------------------------------- /lib/docs_doctor/runner.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/lib/docs_doctor/runner.rb -------------------------------------------------------------------------------- /lib/docs_doctor/task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :docs do 4 | task :play do 5 | parser = DocsDoctor::Runner.new("ruby/rdoc", "4.0.0").parser 6 | puts parser.inspect 7 | parser.add_files("test/fixtures/ruby/string/strip.rb") 8 | parser.go! 9 | end 10 | end 11 | 12 | # parser = DocsDoctor::Parser.new('ruby/rdoc', '4.0.0') 13 | # parser.add_files("/Users/schneems/Documents/projects/rails/activesupport/lib/active_support/core_ext/string/strip.rb") 14 | # parser.go! 15 | 16 | # parser.files.each do |file| 17 | # file.classes.each do |klass| 18 | # klass.methods.each do |method| 19 | 20 | # end 21 | # end 22 | # end 23 | -------------------------------------------------------------------------------- /lib/sorted_repo_collection.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SortedRepoCollection 4 | include Enumerable 5 | 6 | def initialize(repos) 7 | @repos = repos.sort_by { |r| r.fetch("full_name").downcase } 8 | end 9 | 10 | def each 11 | @repos.each { |r| yield r } 12 | end 13 | 14 | def size 15 | @repos.length 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/tasks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/lib/tasks/.gitkeep -------------------------------------------------------------------------------- /lib/tasks/performance.rake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/lib/tasks/performance.rake -------------------------------------------------------------------------------- /lib/tasks/test.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # namespace 'test' do 4 | # desc "Run the javascript test" 5 | # task javascript: :environment do 6 | # require "teaspoon/console" 7 | # puts "\n\n===== Starting Javascript Test =====\n\n" 8 | # fail if Teaspoon::Console.new({suite: ENV["suite"]}).execute 9 | # puts "===== Javascript Test Complete =====\n\n\n" 10 | # end 11 | # end 12 | 13 | # Rake::Task[:test].enhance(['test:javascript']) 14 | -------------------------------------------------------------------------------- /log/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codetriage/CodeTriage/2f193418ca0b8757ca0a1159a2e7827ff5a02926/log/.gitkeep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /perf.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler" 4 | Bundler.setup 5 | 6 | require "derailed_benchmarks" 7 | require "derailed_benchmarks/tasks" 8 | 9 | ENV["RAILS_LOG_TO_STDOUT"] ||= "1" 10 | ENV["RAILS_SERVE_STATIC_FILES"] ||= "1" 11 | ENV["SECRET_KEY_BASE"] ||= "lol" 12 | ENV["DEVISE_SECRET_KEY"] ||= "lol" 13 | -------------------------------------------------------------------------------- /perf_scripts/cache_version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "active_record" 4 | 5 | ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") 6 | ActiveRecord::Base.cache_versioning = true 7 | 8 | ActiveRecord::Schema.define do 9 | create_table :users, force: true do |t| 10 | t.string :name 11 | t.timestamps null: false 12 | end 13 | 14 | create_table :topics, force: true do |t| 15 | t.string :title 16 | t.integer :user_id 17 | t.timestamps null: false 18 | end 19 | end 20 | 21 | class Topic < ActiveRecord::Base 22 | belongs_to :user 23 | end 24 | 25 | class User < ActiveRecord::Base 26 | has_many :topics 27 | end 28 | 29 | mass_user_create = 1000.times.each.map do 30 | {name: "user"} 31 | end 32 | 33 | User.create(mass_user_create) 34 | 35 | ALL_USERS = User.all 36 | 37 | puts ALL_USERS.first.method(:cache_version).source_location 38 | 39 | Benchmark.bm { |x| 40 | x.report("title_was") { 41 | ALL_USERS.each do |user| 42 | user.cache_version 43 | end 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /perf_scripts/dirty_tracking.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "active_record" 4 | 5 | ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") 6 | 7 | ActiveRecord::Schema.define do 8 | create_table :users, force: true do |t| 9 | t.string :name 10 | t.timestamps null: false 11 | end 12 | 13 | create_table :topics, force: true do |t| 14 | t.string :title 15 | t.integer :user_id 16 | t.timestamps null: false 17 | end 18 | end 19 | 20 | class Topic < ActiveRecord::Base 21 | belongs_to :user 22 | end 23 | 24 | class User < ActiveRecord::Base 25 | has_many :topics 26 | end 27 | 28 | user = User.create!(name: "user name") 29 | topic = user.topics.build(title: "topic title") 30 | 31 | # Benchmark.ips do |x| 32 | # x.report("changed?") { topic.changed? } 33 | # x.report("changed") { topic.changed } 34 | # x.report("changes") { topic.changes } 35 | # x.report("changed_attributes") { topic.changed_attributes } 36 | # x.report("title_change") { topic.title_change } 37 | # x.report("title_was") { topic.title_was } 38 | # end 39 | 40 | Benchmark.bm { |x| 41 | x.report("title_was") { 42 | 1_000_000.times { 43 | topic.title_was 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /perf_scripts/partial_cache.rb: -------------------------------------------------------------------------------- 1 | require "benchmark/ips" 2 | require "action_view" 3 | require "action_pack" 4 | require "action_controller" 5 | require "active_record" 6 | require "stackprof" 7 | 8 | ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") 9 | 10 | ActiveRecord::Schema.define do 11 | create_table :customers, force: true do |t| 12 | t.string :name 13 | end 14 | end 15 | 16 | class Customer < ActiveRecord::Base; end 17 | 18 | class TestController < ActionController::Base 19 | end 20 | 21 | ActionView::PartialRenderer.collection_cache = ActiveSupport::Cache::MemoryStore.new 22 | TestController.view_paths = [File.expand_path("perf_scripts/partial_cache")] 23 | 24 | puts TestController.view_paths 25 | 26 | # Create a bunch of data 27 | 28 | letters = ("a".."z").to_a * 5 29 | 1000.times { Customer.create!(name: letters.sample(10).join) } 30 | 31 | customers = Customer.all.to_a 32 | 33 | controller_view = TestController.new.view_context 34 | 35 | # Heat compilation cache and collection cache 36 | controller_view.render("render_collection", customers: customers) 37 | controller_view.render("render_collection_with_cache", customers: customers) 38 | 39 | p ActionView::PartialRenderer.collection_cache # 1000 entries 40 | 41 | Benchmark.ips do |x| 42 | x.report("collection render: no cache") do 43 | controller_view.render("render_collection", customers: customers) 44 | end 45 | 46 | x.report("collection render: with cache") do 47 | controller_view.render("render_collection_with_cache", customers: customers) 48 | end 49 | 50 | x.compare! 51 | end 52 | -------------------------------------------------------------------------------- /perf_scripts/partial_cache/test/_customer.html.erb: -------------------------------------------------------------------------------- 1 | _customer.html.erb 2 |
You may have mistyped the address or the page may have moved.
56 | 57 | Home | 58 | Repos 59 | 60 |Maybe you tried to change something you didn't have access to.
24 |