├── .codoopts ├── .gitignore ├── .rspec ├── .ruby-gemset ├── .ruby-version ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.d ├── _before.rb ├── assets.rb ├── authentication.rb ├── concurrency.rb ├── development.rb ├── dogfood.rb ├── framework.rb ├── integration.rb ├── mail.rb ├── models.rb ├── specs.rb ├── utilities.rb ├── views.rb └── ~after.rb ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ ├── bug.png │ │ ├── comment-arrow.png │ │ └── footer.png │ ├── javascripts │ │ ├── aggregation.js.coffee │ │ ├── application.js │ │ ├── flash.js.coffee │ │ ├── histogram.js.coffee │ │ ├── navbar.js.coffee │ │ └── search.js.coffee │ └── stylesheets │ │ ├── _alerts.scss │ │ ├── _badges.scss │ │ ├── _breadcrumbs.scss │ │ ├── _containers.scss │ │ ├── _controls.scss │ │ ├── _footer.scss │ │ ├── _forms.scss │ │ ├── _modal.scss │ │ ├── _navbar.scss │ │ ├── _pills.scss │ │ ├── _tables.scss │ │ ├── _typography.scss │ │ ├── _vars.scss │ │ ├── accounts.css.scss │ │ ├── application.css │ │ ├── bugs.css.scss │ │ ├── feed.css.scss │ │ ├── flash.css.scss │ │ ├── membership.css.scss │ │ ├── occurrences.css.scss │ │ ├── projects.css.scss │ │ ├── sessions.css.scss │ │ ├── squash.css.scss │ │ └── users.css.scss ├── controllers │ ├── account │ │ ├── bugs_controller.rb │ │ ├── events_controller.rb │ │ └── memberships_controller.rb │ ├── accounts_controller.rb │ ├── additions │ │ ├── authentication_helpers.rb │ │ ├── event_decoration.rb │ │ ├── json_detail_responder.rb │ │ ├── ldap_authentication_helpers.rb │ │ └── password_authentication_helpers.rb │ ├── api │ │ └── v1_controller.rb │ ├── application_controller.rb │ ├── bugs_controller.rb │ ├── comments_controller.rb │ ├── commits_controller.rb │ ├── emails_controller.rb │ ├── environments_controller.rb │ ├── events_controller.rb │ ├── jira │ │ ├── issues_controller.rb │ │ ├── projects_controller.rb │ │ └── statuses_controller.rb │ ├── notification_thresholds_controller.rb │ ├── occurrences_controller.rb │ ├── project │ │ ├── membership_controller.rb │ │ └── memberships_controller.rb │ ├── projects_controller.rb │ ├── search_controller.rb │ ├── sessions_controller.rb │ └── users_controller.rb ├── helpers │ ├── application_helper.rb │ ├── mail_helper.rb │ └── occurrences_helper.rb ├── mailers │ ├── .gitkeep │ └── notification_mailer.rb ├── middleware │ └── ping.rb ├── models │ ├── .gitkeep │ ├── additions │ │ ├── ldap_authentication.rb │ │ └── password_authentication.rb │ ├── blame.rb │ ├── bug.rb │ ├── comment.rb │ ├── deploy.rb │ ├── device_bug.rb │ ├── email.rb │ ├── environment.rb │ ├── event.rb │ ├── membership.rb │ ├── notification_threshold.rb │ ├── obfuscation_map.rb │ ├── observers │ │ ├── bug_observer.rb │ │ ├── comment_observer.rb │ │ ├── deploy_observer.rb │ │ ├── event_observer.rb │ │ ├── occurrence_observer.rb │ │ └── watch_observer.rb │ ├── occurrence.rb │ ├── project.rb │ ├── slug.rb │ ├── source_map.rb │ ├── symbolication.rb │ ├── user.rb │ ├── user_event.rb │ └── watch.rb └── views │ ├── accounts │ ├── show.html.rb │ └── show.js.erb │ ├── additions │ ├── accordion.rb │ ├── html_backtrace_rendering.rb │ └── text_backtrace_rendering.rb │ ├── bugs │ ├── index.atom.builder │ ├── index.html.rb │ ├── index.js.erb │ ├── show.html.rb │ └── show.js.erb │ ├── layouts │ └── application.html.rb │ ├── notification_mailer │ ├── assign.text.erb │ ├── blame.text.erb │ ├── comment.text.erb │ ├── critical.text.erb │ ├── deploy.text.erb │ ├── initial.text.erb │ ├── occurrence.text.erb │ ├── reopened.text.erb │ ├── resolved.text.erb │ └── threshold.text.erb │ ├── occurrences │ ├── index.atom.builder │ ├── show.html.rb │ └── show.js.erb │ ├── project │ └── membership │ │ ├── edit.html.rb │ │ └── edit.js.erb │ ├── projects │ ├── edit.html.rb │ ├── edit.js.erb │ ├── index.html.rb │ ├── index.js.erb │ ├── show.html.rb │ └── show.js.erb │ ├── sessions │ └── new.html.rb │ └── users │ └── show.html.rb ├── bin ├── bundle ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── common │ │ ├── activerecord.yml │ │ ├── authentication.yml │ │ ├── concurrency.yml │ │ ├── dogfood.yml │ │ ├── javascript_dogfood.yml │ │ ├── jira.yml │ │ ├── mailer.yml │ │ ├── pagerduty.yml │ │ └── repositories.yml │ ├── development.rb │ ├── development │ │ ├── dogfood.yml │ │ └── mailer.yml │ ├── production.rb │ ├── production │ │ ├── dogfood.yml │ │ ├── javascript_dogfood.yml │ │ └── mailer.yml │ ├── test.rb │ └── test │ │ ├── dogfood.yml │ │ ├── jira.yml │ │ ├── mailer.yml │ │ ├── people.yml │ │ └── squash_javascript.yml ├── initializers │ ├── active_record.rb │ ├── active_record_observer_hooks.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── concurrency.rb │ ├── cookies_serializer.rb │ ├── dogfood.rb │ ├── field_error_proc.rb │ ├── filter_parameter_logging.rb │ ├── find_in_batches.rb │ ├── html5.rb │ ├── inflections.rb │ ├── jdbc_fixes.rb │ ├── jira.rb │ ├── load_autoload_paths.rb │ ├── mail.rb │ ├── mime_types.rb │ ├── secret_token.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── preinitializers │ ├── jruby.rb │ ├── safe_yaml.rb │ └── source_maps.rb ├── routes.rb └── secrets.yml ├── data ├── brushes.yml └── message_templates.yml ├── db ├── .gitignore ├── migrate │ ├── 1_initial_schema.rb │ ├── 20130125021927_index_occurrences_by_bug_and_redirected.rb │ ├── 20130131002457_track_crashes.rb │ ├── 20130131002503_track_bugs_per_device.rb │ ├── 20130215185809_fix_condition_on_rule_occurrences_set_latest.rb │ ├── 20130221020818_create_blames.rb │ ├── 20130222055524_fix_blame_lru_key.rb │ ├── 20140130012355_add_mapping_to_source_map.rb │ └── 20151126022941_add_hosted_filename_to_source_maps.rb └── seeds.rb ├── doc ├── .gitignore ├── CONTRIBUTING.md ├── MAKING_A_CLIENT_LIBRARY.md └── fdoc │ ├── deobfuscation-POST.fdoc │ ├── deploy-POST.fdoc │ ├── notify-POST.fdoc │ ├── sourcemap-POST.fdoc │ ├── squash.fdoc.service │ └── symbolication-POST.fdoc ├── lib ├── api │ └── errors.rb ├── assets │ ├── .gitkeep │ ├── javascripts │ │ ├── accordion.js.coffee │ │ ├── autocomplete.js.coffee │ │ ├── bug_file_formatter.js.coffee │ │ ├── buttons.js.coffee │ │ ├── configure_squash_client.js.coffee.erb │ │ ├── context.js.coffee │ │ ├── disclosure.js.coffee │ │ ├── dropdown.js.coffee │ │ ├── dynamic_search_field.js.coffee │ │ ├── editor_links.js.coffee │ │ ├── email_alias_form.js.coffee │ │ ├── error_tooltip.js.coffee │ │ ├── feed.js.coffee │ │ ├── form_with_errors.js.coffee │ │ ├── live_update.js.coffee │ │ ├── member_panel.js.coffee │ │ ├── smart_form.js.coffee │ │ ├── sortable_table.js.coffee │ │ ├── tabs.js.coffee │ │ ├── utilities.js.coffee │ │ └── value_inspector.js.coffee │ └── stylesheets │ │ ├── accordion.css.scss │ │ ├── autocomplete.css.scss │ │ ├── grid.css.scss │ │ ├── reset.css │ │ ├── smart_form.css.scss │ │ └── sortable_table.css.scss ├── background_runner.rb ├── background_runner │ ├── job.rb │ ├── multithread.rb │ ├── resque.rb │ ├── sidekiq.rb │ └── tasks │ │ ├── resque.rake │ │ └── sidekiq.rake ├── blamer │ ├── base.rb │ ├── cache.rb │ ├── recency.rb │ └── simple.rb ├── file_mutex.rb ├── known_revision_validator.rb ├── message_template_matcher.rb ├── multithread.rb ├── repo_proxy.rb ├── service.rb ├── service │ ├── jira.rb │ └── pager_duty.rb ├── sidekiq_auth_constraint.rb ├── tasks │ ├── .gitkeep │ ├── concurrency.rake │ ├── doc.rake │ ├── jira.rake │ ├── spec.rake │ ├── statistics.rake │ └── truncation.rake └── workers │ ├── comment_notification_mailer.rb │ ├── deploy_fix_marker.rb │ ├── deploy_notification_mailer.rb │ ├── jira_status_worker.rb │ ├── obfuscation_map_creator.rb │ ├── obfuscation_map_worker.rb │ ├── occurrence_notification_mailer.rb │ ├── occurrences_worker.rb │ ├── pager_duty_acknowledger.rb │ ├── pager_duty_notifier.rb │ ├── pager_duty_resolver.rb │ ├── project_repo_fetcher.rb │ ├── source_map_creator.rb │ ├── source_map_worker.rb │ ├── symbolication_creator.rb │ └── symbolication_worker.rb ├── log └── .gitignore ├── public ├── 400.html ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt ├── script ├── all_specs.sh ├── jira_oauth.rb ├── mysql_message_templates.rb └── psql_message_templates.rb ├── spec ├── controllers │ ├── account │ │ ├── bugs_controller_spec.rb │ │ ├── events_controller_spec.rb │ │ └── memberships_controller_spec.rb │ ├── accounts_controller_spec.rb │ ├── additions │ │ ├── authentication_helpers_spec.rb │ │ ├── ldap_authentication_helpers_spec.rb │ │ └── password_authentication_helpers_spec.rb │ ├── api │ │ └── v1_controller_spec.rb │ ├── application_controller_spec.rb │ ├── bugs_controller_spec.rb │ ├── comments_controller_spec.rb │ ├── commits_controller_spec.rb │ ├── emails_controller_spec.rb │ ├── environments_controller_spec.rb │ ├── events_controller_spec.rb │ ├── jira │ │ ├── issues_controller_spec.rb │ │ ├── projects_controller_spec.rb │ │ └── statuses_controller_spec.rb │ ├── notification_thresholds_controller_spec.rb │ ├── occurrences_controller_spec.rb │ ├── project │ │ ├── membership_controller_spec.rb │ │ └── memberships_controller_spec.rb │ ├── projects_controller_spec.rb │ ├── search_controller_spec.rb │ ├── sessions_controller_spec.rb │ └── users_controller_spec.rb ├── factories │ ├── blames.rb │ ├── bugs.rb │ ├── comments.rb │ ├── deploys.rb │ ├── device_bugs.rb │ ├── emails.rb │ ├── environments.rb │ ├── events.rb │ ├── memberships.rb │ ├── notification_thresholds.rb │ ├── obfuscation_maps.rb │ ├── occurrences.rb │ ├── projects.rb │ ├── source_maps.rb │ ├── symbolications.rb │ ├── user_events.rb │ ├── users.rb │ └── watches.rb ├── fixtures │ ├── image.jpg │ ├── image.png │ ├── jira_issue.json │ ├── jira_issue_404.json │ ├── jira_issue_resolved.json │ ├── jira_projects.json │ ├── jira_statuses.json │ ├── mapping.json │ └── pagerduty_response.json ├── lib │ ├── blamer │ │ ├── cache_spec.rb │ │ ├── recency_spec.rb │ │ └── simple_spec.rb │ ├── composite_primary_keys_spec.rb │ ├── find_in_batches_spec.rb │ ├── known_revision_validator_spec.rb │ ├── message_template_matcher_spec.rb │ ├── multithread_spec.rb │ ├── service │ │ ├── jira_spec.rb │ │ └── pager_duty_spec.rb │ └── workers │ │ ├── deploy_fix_marker_spec.rb │ │ ├── jira_status_updater_spec.rb │ │ └── occurrences_worker_spec.rb ├── mailers │ └── notification_mailer_spec.rb ├── models │ ├── blame_spec.rb │ ├── bug_spec.rb │ ├── comment_spec.rb │ ├── deploy_spec.rb │ ├── device_bug_spec.rb │ ├── email_spec.rb │ ├── environment_spec.rb │ ├── event_spec.rb │ ├── membership_spec.rb │ ├── notification_threshold_spec.rb │ ├── obfuscation_map_spec.rb │ ├── occurrence_spec.rb │ ├── project_spec.rb │ ├── source_map_spec.rb │ ├── symbolication_spec.rb │ ├── user_event_spec.rb │ ├── user_spec.rb │ └── watch_spec.rb ├── rails_helper.rb ├── routing │ ├── project │ │ └── memberships_spec.rb │ └── users_spec.rb ├── spec_helper.rb └── support │ └── controller_404_examples.rb ├── tmp ├── pids │ └── .gitignore ├── repos │ └── .gitignore ├── sessions │ └── .gitignore ├── sockets │ └── .gitignore └── sourcemaps │ └── .gitignore └── vendor ├── assets ├── javascripts │ ├── .gitkeep │ ├── bootstrap.js │ ├── cubism.js │ ├── flot │ │ ├── categories.js │ │ ├── colorhelpers.js │ │ ├── crosshair.js │ │ ├── errorbars.js │ │ ├── excanvas.js │ │ ├── fillbetween.js │ │ ├── flot.js │ │ ├── image.js │ │ ├── navigate.js │ │ ├── pie.js │ │ ├── resize.js │ │ ├── selection.js │ │ ├── stack.js │ │ ├── symbol.js │ │ ├── threshold.js │ │ └── time.js │ ├── jquery-cookie.js │ ├── jquery-leanModal.js │ ├── jquery-timers.js │ └── sh │ │ ├── shAutoloader.js │ │ ├── shBrushAS3.js │ │ ├── shBrushAppleScript.js │ │ ├── shBrushBash.js │ │ ├── shBrushCSharp.js │ │ ├── shBrushColdFusion.js │ │ ├── shBrushCpp.js │ │ ├── shBrushCss.js │ │ ├── shBrushDelphi.js │ │ ├── shBrushDiff.js │ │ ├── shBrushErlang.js │ │ ├── shBrushGit.js │ │ ├── shBrushGroovy.js │ │ ├── shBrushHaxe.js │ │ ├── shBrushJScript.js │ │ ├── shBrushJava.js │ │ ├── shBrushJavaFX.js │ │ ├── shBrushObjC.js │ │ ├── shBrushPerl.js │ │ ├── shBrushPhp.js │ │ ├── shBrushPlain.js │ │ ├── shBrushPowerShell.js │ │ ├── shBrushPython.js │ │ ├── shBrushRuby.js │ │ ├── shBrushSass.js │ │ ├── shBrushScala.js │ │ ├── shBrushSql.js │ │ ├── shBrushTAP.js │ │ ├── shBrushTypeScript.js │ │ ├── shBrushVb.js │ │ ├── shBrushXml.js │ │ ├── shBrushYaml.js │ │ ├── shCore.js │ │ ├── shCore.min.js │ │ └── shLegacy.js └── stylesheets │ ├── .gitkeep │ ├── bootstrap.css │ └── sh │ ├── shCore.css │ ├── shCoreDefault.css │ ├── shCoreDjango.css │ ├── shCoreEclipse.css │ ├── shCoreEmacs.css │ ├── shCoreFadeToGrey.css │ ├── shCoreMDUltra.css │ ├── shCoreMidnight.css │ ├── shCoreRDark.css │ ├── shThemeDefault.css │ ├── shThemeDjango.css │ ├── shThemeEclipse.css │ ├── shThemeEmacs.css │ ├── shThemeFadeToGrey.css │ ├── shThemeMDUltra.css │ ├── shThemeMidnight.css │ └── shThemeRDark.css ├── configoro ├── base.rb ├── hash.rb └── simple.rb └── plugins └── .gitkeep /.codoopts: -------------------------------------------------------------------------------- 1 | -o doc/js 2 | --title "Squash Front-End JavaScript Documentation" 3 | 4 | lib/assets/javascripts 5 | app/assets/javascripts 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | .yardoc 3 | node_modules 4 | tmp/cache/* 5 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | --format documentation 4 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | squash 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.0 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | doc/CONTRIBUTING.md -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Load all files under the Gemfile.d directory. 4 | 5 | Dir.glob(File.join(File.dirname(__FILE__), 'Gemfile.d', '*.rb')).sort.each do |file| 6 | eval File.read(file), binding, file 7 | end 8 | -------------------------------------------------------------------------------- /Gemfile.d/_before.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Load our frozen Configoro 16 | require File.join(File.dirname(__FILE__), '..', 'vendor', 'configoro', 'simple') 17 | 18 | rails_root = ENV['RAILS_ROOT'] || File.join(File.dirname(__FILE__), '..') 19 | Configoro.paths << File.join(rails_root, 'config', 'environments') 20 | 21 | $_squash_environments = Dir.glob(File.join(rails_root, 'config', 'environments', '*.rb')).map { |f| File.basename f, '.rb' } 22 | 23 | def load_groups(configuration_path, values) 24 | configuration_path = configuration_path.split('.') 25 | 26 | $_squash_environments.select do |env| 27 | settings = Configoro.load_environment(env) 28 | values.include?(traverse_hash(settings, *configuration_path)) 29 | end 30 | end 31 | 32 | def traverse_hash(hsh, *keys) 33 | return nil unless hsh 34 | 35 | if keys.size == 1 36 | hsh[keys.first] 37 | else 38 | traverse_hash hsh[keys.shift], *keys 39 | end 40 | end 41 | 42 | def conditionally(configuration_path, *values, &block) 43 | groups = load_groups(configuration_path, values) 44 | groups.each { |g| group g.to_sym, &block } 45 | end 46 | -------------------------------------------------------------------------------- /Gemfile.d/assets.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'sass-rails' 16 | gem 'sprockets' # fix nil error 17 | gem 'libv8', platform: :mri 18 | gem 'therubyracer', platform: :mri 19 | gem 'therubyrhino', platform: :jruby 20 | gem 'less-rails' 21 | 22 | gem 'font-awesome-rails' 23 | 24 | gem 'coffee-rails' 25 | gem 'closure-compiler' 26 | gem 'jquery-rails' 27 | -------------------------------------------------------------------------------- /Gemfile.d/authentication.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | conditionally('authentication.strategy', 'ldap') do 16 | gem 'net-ldap', github: 'ruby-ldap/ruby-net-ldap', require: 'net/ldap' 17 | end 18 | -------------------------------------------------------------------------------- /Gemfile.d/concurrency.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | conditionally('concurrency.background_runner', 'Resque') do 16 | gem 'resque' 17 | gem 'resque-pool' 18 | end 19 | 20 | conditionally('concurrency.background_runner', 'Sidekiq') do 21 | gem 'sidekiq' 22 | gem 'capistrano-sidekiq' 23 | 24 | # disable if you don't need Sidekiq monitoring 25 | gem 'slim' 26 | gem 'sinatra' 27 | end 28 | -------------------------------------------------------------------------------- /Gemfile.d/development.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | group :development do 16 | gem 'yard', require: nil 17 | gem 'redcarpet', require: nil, platform: :mri 18 | end 19 | 20 | gem 'sql_origin', groups: [:development, :test] 21 | -------------------------------------------------------------------------------- /Gemfile.d/dogfood.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'squash_ruby', require: 'squash/ruby' 16 | gem 'squash_rails', require: 'squash/rails' 17 | gem 'squash_ios_symbolicator', require: 'squash/symbolicator' 18 | gem 'squash_javascript', require: 'squash/javascript' 19 | gem 'sourcemap' 20 | gem 'squash_java', require: 'squash/java' 21 | -------------------------------------------------------------------------------- /Gemfile.d/framework.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'rails', '4.2.5.2' 16 | gem 'responders' 17 | gem 'psych' # fix TypeError: superclass mismatch for class Mark 18 | 19 | gem 'configoro' 20 | gem 'rack-cors', require: 'rack/cors' 21 | -------------------------------------------------------------------------------- /Gemfile.d/integration.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | conditionally('jira.disabled', false, nil) do 16 | gem 'jira-ruby', require: 'jira' 17 | end 18 | -------------------------------------------------------------------------------- /Gemfile.d/mail.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | conditionally('mailer.smtp_settings.authentication', 'ntlm') do 16 | gem 'ruby-ntlm', require: 'ntlm/smtp' 17 | end 18 | 19 | -------------------------------------------------------------------------------- /Gemfile.d/models.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'pg', platform: :mri 16 | gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby 17 | gem 'has_metadata_column' 18 | gem 'slugalicious' 19 | gem 'email_validation' 20 | gem 'url_validation' 21 | gem 'json_serialize' 22 | gem 'validates_timeliness' 23 | gem 'find_or_create_on_scopes' 24 | gem 'composite_primary_keys' 25 | gem 'rails-observers' 26 | 27 | conditionally('activerecord.cursors', true) do 28 | gem 'activerecord-postgresql-cursors' 29 | end 30 | -------------------------------------------------------------------------------- /Gemfile.d/specs.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | group :test do 16 | gem 'rspec-rails' 17 | gem 'factory_girl_rails' 18 | 19 | gem 'fakeweb' 20 | end 21 | -------------------------------------------------------------------------------- /Gemfile.d/utilities.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'json' 16 | gem 'git', github: 'RISCfuture/ruby-git' 17 | gem 'user-agent' 18 | 19 | gem 'safe_yaml' 20 | -------------------------------------------------------------------------------- /Gemfile.d/views.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gem 'erector', github: 'RISCfuture/erector' 16 | gem 'kramdown' 17 | -------------------------------------------------------------------------------- /Gemfile.d/~after.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | if defined?(Configoro) 16 | Configoro.reset_paths # reset configoro 17 | end 18 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | 3 | # Copyright 2014 Square Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Add your own tasks in files placed in lib/tasks ending in .rake, 18 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 19 | 20 | require File.expand_path('../config/application', __FILE__) 21 | 22 | Squash::Application.load_tasks 23 | -------------------------------------------------------------------------------- /app/assets/images/bug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/app/assets/images/bug.png -------------------------------------------------------------------------------- /app/assets/images/comment-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/app/assets/images/comment-arrow.png -------------------------------------------------------------------------------- /app/assets/images/footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/app/assets/images/footer.png -------------------------------------------------------------------------------- /app/assets/stylesheets/_alerts.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | .alert { 4 | padding: 10px 20px; 5 | border-radius: 4px; 6 | font-weight: bold; 7 | margin: 20px 0; 8 | 9 | &.error { background-color: $red; } 10 | &.important { background-color: $orange; } 11 | &.warning { background-color: $yellow; } 12 | &.success { background-color: $green; } 13 | &.info { background-color: $blue; } 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_badges.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | $badge-padding: 4px; 4 | 5 | span.badge { 6 | background-color: $gray3; 7 | color: white; 8 | padding: $badge-padding; 9 | border-radius: $radius-size; 10 | 11 | &.critical { background-color: $red; } 12 | &.important { background-color: $orange; color: black; } 13 | &.warning { background-color: $yellow; color: black; } 14 | &.success { background-color: $green; color: black; } 15 | &.info { background-color: $blue; color: black; } 16 | } 17 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | #breadcrumbs-container .container { 4 | display: -webkit-box; 5 | display: -moz-box; 6 | display: box; 7 | } 8 | 9 | ul.breadcrumb { 10 | background-color: white; 11 | padding: 0 20px; 12 | line-height: $nav-height; 13 | 14 | -webkit-box-flex: 1; 15 | -moz-box-flex: 1; 16 | box-flex: 1; 17 | 18 | li { 19 | display: inline; 20 | 21 | a { text-decoration: none; } 22 | &:last-child { 23 | font-size: 14px; 24 | font-weight: bold; 25 | } 26 | 27 | &.divider { 28 | color: $gray4; 29 | padding: 0 5px; 30 | } 31 | } 32 | } 33 | 34 | div#breadcrumbs-stats { 35 | display: -webkit-box; 36 | display: -moz-box; 37 | display: box; 38 | 39 | div { 40 | margin: 13px 5px; 41 | background-color: $gray5; 42 | padding: 4px 10px; 43 | border-radius: $radius-size; 44 | 45 | strong { 46 | font-size: 14px; 47 | font-weight: bold; 48 | margin: 0; 49 | } 50 | 51 | span { 52 | font-size: 14px; 53 | display: none; 54 | } 55 | 56 | &.shown span { display: inline; } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_controls.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | @mixin button($color) { 4 | background: $color; 5 | border: none; 6 | border-radius: $radius-size; 7 | display: inline-block; 8 | color: $gray3; 9 | font-size: $control-font-size; 10 | font-weight: bold; 11 | text-transform: uppercase; 12 | text-decoration: none; 13 | padding: 5px 10px; 14 | 15 | &:hover { cursor: pointer; } 16 | 17 | &:active { 18 | position: relative; 19 | top: 1px; 20 | } 21 | 22 | &[disabled], &.disabled { 23 | background: lighten($color, 15%); 24 | color: $gray5; 25 | } 26 | 27 | &.small { 28 | font-size: 11px; 29 | padding: 2px 5px; 30 | } 31 | } 32 | 33 | input[type=button], input[type=submit], button, .button { 34 | @include button($darkblue); 35 | &.default { @include button($orange); } 36 | &.success { @include button($darkgreen); } 37 | &.warning { @include button($red); } 38 | } 39 | 40 | input[type=text], input[type=email], input[type=password], input[type=search], input[type=tel], input[type=number], textarea { 41 | @include field-options; 42 | width: 100%; 43 | border: none; 44 | border-radius: $radius-size; 45 | } 46 | 47 | select { 48 | font-size: $control-font-size; 49 | width: 100%; 50 | padding: 5px 10px; 51 | } 52 | 53 | input[type=search] { 54 | -webkit-appearance: textfield; 55 | border-radius: $radius-size*2; 56 | width: 100%; // webkit likes to fix these at 125px 57 | } 58 | 59 | input.error, select.error, textarea.error { 60 | background-color: $red !important; 61 | } 62 | 63 | input:invalid, textarea:invalid, select:invalid { border: 1px solid $red !important; } 64 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_footer.scss: -------------------------------------------------------------------------------- 1 | footer { 2 | p { 3 | text-align: center; 4 | color: rgb(159, 159, 159); 5 | margin-top: 20px; 6 | margin-bottom: 10px; 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_modal.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | #lean_overlay { 4 | position: fixed; 5 | z-index: 100; 6 | top: 0px; 7 | left: 0px; 8 | height: 100%; 9 | width: 100%; 10 | background: black; 11 | display: none; 12 | } 13 | 14 | .modal { 15 | display: none; 16 | 17 | &>a.close { 18 | position: absolute; 19 | top: 0px; 20 | right: 10px; 21 | font-size: 20px; 22 | font-weight: bold; 23 | color: rgba(black, 0.5); 24 | text-decoration: none; 25 | &:hover { color: black; } 26 | } 27 | 28 | &>.modal-body { 29 | background-color: $gray5; 30 | border-bottom-left-radius: $radius-size; 31 | border-bottom-right-radius: $radius-size; 32 | padding: 10px 50px; 33 | 34 | .accordion { 35 | .accordion-pair>h5 { background-color: $gray4; } 36 | 37 | } 38 | } 39 | 40 | h1 { 41 | background-color: white; 42 | padding: 40px 35px 20px 35px; 43 | margin: 0; 44 | } 45 | 46 | p { margin: 5px 10px 15px 10px; } 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_pills.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | ul.pills { 4 | margin-top: 30px; 5 | margin-bottom: 20px; 6 | padding-bottom: 10px; 7 | text-align: center; 8 | border-bottom: 1px solid $gray4; 9 | 10 | &:first-child { margin-top: 0; } 11 | 12 | li { 13 | display: inline; 14 | padding-left: 10px; 15 | padding-right: 10px; 16 | border-right: 1px solid black; 17 | margin-top: 30px; 18 | margin-bottom: 10px; 19 | 20 | &:last-child { border-right: none; } 21 | &.active { font-weight: bold; } 22 | 23 | a { text-decoration: none; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/assets/stylesheets/_tables.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | @mixin table { 4 | th { 5 | font-weight: bold; 6 | font-size: 11px; 7 | color: $gray2; 8 | text-transform: uppercase; 9 | text-align: left; 10 | background-color: $gray6; 11 | padding: 10px 20px; 12 | white-space: nowrap; 13 | } 14 | 15 | tr { background-color: #f4f4f4; } 16 | tbody>tr:hover:not(.no-highlight) { background-color: white; } 17 | 18 | td { 19 | padding: 10px 20px; 20 | border-bottom: 1px solid $gray5; 21 | 22 | &.table-notice { 23 | padding-top: 20px; 24 | color: $gray4; 25 | font-size: 30px; 26 | font-weight: bold; 27 | text-align: center; 28 | cursor: inherit; 29 | background-color: transparent !important; 30 | } 31 | } 32 | 33 | .no-results { 34 | padding-top: 20px; 35 | color: $gray4; 36 | font-size: 30px; 37 | font-weight: bold; 38 | text-align: center; 39 | } 40 | 41 | a.rowlink { 42 | color: inherit; 43 | text-decoration: none; 44 | } 45 | 46 | tr:hover a.rowlink { text-decoration: underline; } 47 | 48 | @include iphone-landscape-and-smaller { 49 | // for small screens, turn the table on its head: stack the cells of a row 50 | // and create a clear division between these groups 51 | 52 | tr { 53 | display: block; 54 | border-bottom: 3px solid $gray4; 55 | } 56 | 57 | thead>tr { 58 | border-top: 3px solid $gray4; 59 | } 60 | 61 | td, th { display: block; } 62 | td { border-bottom: 1px solid $gray5; } 63 | td:last-child { border-bottom: none; } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/assets/stylesheets/accounts.css.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | body.accounts { 4 | h1 img { 5 | height: $h1-size; 6 | vertical-align: bottom; 7 | margin-right: 10px; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | * 13 | *= require reset 14 | *= require grid 15 | * 16 | *= require bootstrap 17 | *= require font-awesome 18 | *= require sh/shCoreDefault 19 | * 20 | *= require accordion 21 | *= require autocomplete 22 | *= require smart_form 23 | *= require sortable_table 24 | * 25 | *= require squash 26 | *= 27 | *= require accounts 28 | *= require bugs 29 | *= require feed 30 | *= require flash 31 | *= require membership 32 | *= require occurrences 33 | *= require projects 34 | *= require sessions 35 | *= require users 36 | */ 37 | -------------------------------------------------------------------------------- /app/assets/stylesheets/flash.css.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | #flashes { 4 | position: fixed; 5 | bottom: 0; 6 | left: 0; 7 | width: 50%; 8 | } 9 | 10 | @mixin flash($color) { 11 | font-weight: bold; 12 | padding: 10px 20px; 13 | border-top-right-radius: $radius-size; 14 | border-bottom-right-radius: $radius-size; 15 | margin-top: 10px; 16 | margin-bottom: 10px; 17 | background-color: $color; 18 | 19 | // prepare for slide-in animation 20 | position: relative; 21 | left: -100%; 22 | 23 | [class^="fa-"], [class*=" fa-"] { margin-right: 10px; } 24 | a { 25 | float: right; 26 | font-weight: bold; 27 | opacity: 0.5; 28 | &:hover { opacity: 1; } 29 | } 30 | } 31 | 32 | .flash-alert { @include flash($red); } 33 | .flash-notice { @include flash($blue); } 34 | .flash-success { @include flash($green); } 35 | 36 | $flash-animation-duration: 0.5s; 37 | 38 | .flash-shown { 39 | left: 0%; 40 | -webkit-transition: left $flash-animation-duration ease-out; 41 | -moz-transition: left $flash-animation-duration ease-out; 42 | transition: left $flash-animation-duration ease-out; 43 | } 44 | 45 | .flash-hidden { 46 | left: -100%; 47 | -webkit-transition: left $flash-animation-duration ease-in; 48 | -moz-transition: left $flash-animation-duration ease-in; 49 | transition: left $flash-animation-duration ease-in; 50 | } 51 | -------------------------------------------------------------------------------- /app/assets/stylesheets/membership.css.scss: -------------------------------------------------------------------------------- 1 | body#membership-edit { 2 | .row { padding-bottom: 30px; } 3 | 4 | form { 5 | padding-top: 0; 6 | padding-bottom: 0; 7 | } 8 | 9 | #project-owner img { 10 | float: left; 11 | margin-right: 10px; 12 | } 13 | } 14 | 15 | #email-aliases { 16 | input[type=search] { margin-bottom: 10px; } 17 | } 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/sessions.css.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | body.sessions { 4 | .modal-container p { font-size: $h5-size; } 5 | 6 | .body-portion { 7 | h3 { margin-top: 50px; } 8 | 9 | form { 10 | &>div { 11 | margin: 10px 0; 12 | &:last-child { margin-bottom: 0; } 13 | } 14 | 15 | .row .columns { 16 | padding: 0 5px; 17 | &:first-child { padding-left: 0; } 18 | &:last-child { padding-right: 0; } 19 | } 20 | input[type=submit] { width: 100%; } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/squash.css.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | // ----- RESPONSIVE 4 | 5 | @include ipad-and-larger { 6 | .compact-only { display: none; } 7 | } 8 | 9 | @include iphone-landscape-and-smaller { 10 | .full-size-only { display: none; } 11 | } 12 | 13 | // ----- LAYOUT 14 | 15 | // bleed background colors to the bottom of the page 16 | body { 17 | background-color: white; 18 | font-family: "Helvetica Neue", Helvetica, sans-serif; 19 | font-size: $base-font-size; 20 | } 21 | 22 | @import "typography"; 23 | 24 | // ----- PAGE ELEMENTS 25 | 26 | a.favorite { 27 | text-decoration: none; 28 | &:hover { text-decoration: none; } 29 | i { color: $orange; } 30 | } 31 | 32 | .no-results { 33 | padding-top: 20px; 34 | color: $gray4; 35 | font-size: $h2-size; 36 | font-weight: bold; 37 | text-align: center; 38 | } 39 | 40 | img { 41 | max-width: 100%; 42 | height: auto; 43 | } 44 | 45 | // apply to a div containing a gravatar to the left of profile data 46 | .profile-widget img { 47 | width: 40%; 48 | margin-right: 10px; 49 | float: left; 50 | } 51 | 52 | // ----- IMPORTS 53 | 54 | @import "alerts"; 55 | @import "badges"; 56 | @import "breadcrumbs"; 57 | @import "containers"; 58 | @import "controls"; 59 | @import "forms"; 60 | @import "modal"; 61 | @import "navbar"; 62 | @import "pills"; 63 | @import "footer.scss"; 64 | -------------------------------------------------------------------------------- /app/assets/stylesheets/users.css.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | body#users-show { 4 | h1 img { 5 | height: $h1-size; 6 | vertical-align: bottom; 7 | margin-right: 10px; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/controllers/additions/json_detail_responder.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Subclasses `ActionController::Responder` to include a little more detail in 16 | # the JSON response for 422 errors and successful updates. In particular: 17 | # 18 | # * Alters the default response for successful `create` API requests to render 19 | # the resource representation to the response body. 20 | # * Alters the default response for failing `create` and `update` requests to 21 | # render the errors object with the object's class name 22 | # (see {ApplicationController}, section **Typical Responses**). 23 | 24 | class JsonDetailResponder < ActionController::Responder 25 | protected 26 | 27 | # @private 28 | def json_resource_errors 29 | {resource.class.model_name.singular => resource.errors} 30 | end 31 | 32 | # @private 33 | def api_behavior 34 | raise MissingRenderer.new(format) unless has_renderer? 35 | 36 | if put? || patch? 37 | display resource, location: api_location 38 | else 39 | super 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /app/controllers/additions/password_authentication_helpers.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Includes methods for authentication using logins and passwords. Passwords are 16 | # stored as salted, hashed strings in accordance with normal security standards. 17 | 18 | module PasswordAuthenticationHelpers 19 | # Attempts to log in a user, given his/her credentials. If the login fails, 20 | # the reason is logged and tagged with "[AuthenticationHelpers]". If the login 21 | # is successful, the user ID is written to the session. 22 | # 23 | # @param [String] username The username. 24 | # @param [String] password The password. 25 | # @return [true, false] Whether or not the login was successful. 26 | 27 | def log_in(username, password) 28 | user = User.find_by_username(username) 29 | if user && user.authentic?(password) 30 | log_in_user user 31 | return true 32 | else 33 | logger.tagged('AuthenticationHelpers') { logger.info "Denying login to #{username}: Invalid credentials." } 34 | return false 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /app/controllers/jira/issues_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Controller that loads JIRA issues. 16 | 17 | class Jira::IssuesController < ApplicationController 18 | skip_before_filter :login_required 19 | before_filter :find_issue 20 | respond_to :json 21 | 22 | # Returns information about a JIRA issue. 23 | # 24 | # * `GET /jira/issues/:id` 25 | # 26 | # Path Parameters 27 | # --------------- 28 | # 29 | # | | | 30 | # |:-----|----------------------------------------| 31 | # | `id` | The JIRA issue key (e.g., "PROJ-123"). | 32 | 33 | def show 34 | respond_with(@issue) do |format| 35 | format.json { render json: @issue.to_json } 36 | end 37 | end 38 | 39 | private 40 | 41 | def find_issue 42 | @issue = Service::JIRA.issue(params[:id]) || raise(ActiveRecord::RecordNotFound) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /app/controllers/jira/projects_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Controller that loads JIRA projects. 16 | 17 | class Jira::ProjectsController < ApplicationController 18 | skip_before_filter :login_required 19 | respond_to :json 20 | 21 | # Returns a list of JIRA projects. 22 | # 23 | # * `GET /jira/projects` 24 | 25 | def index 26 | @projects = Service::JIRA.projects 27 | respond_with(@projects) do |format| 28 | format.json { render json: @projects.to_a.sort_by(&:name).map(&:attrs).to_json } 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/controllers/jira/statuses_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Controller that loads JIRA issue statuses. 16 | 17 | class Jira::StatusesController < ApplicationController 18 | skip_before_filter :login_required 19 | respond_to :json 20 | 21 | # Returns a list of JIRA statuses. 22 | # 23 | # * `GET /jira/statuses` 24 | 25 | def index 26 | @statuses = Service::JIRA.statuses 27 | respond_with(@statuses) do |format| 28 | format.json { render json: @statuses.to_a.sort_by(&:name).map(&:attrs).to_json } 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/mailers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/app/mailers/.gitkeep -------------------------------------------------------------------------------- /app/middleware/ping.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Rack middleware that responds to a /_status ping before Rack::SSL gets a 16 | # chance to return a redirect to the HTTPS site. 17 | 18 | class Ping 19 | # @private 20 | def initialize(app) 21 | @app = app 22 | end 23 | 24 | # @private 25 | def call(env) 26 | if env['ORIGINAL_FULLPATH'] == '/_status' 27 | [200, {}, ['{"status":"OK"}']] 28 | else 29 | @app.call env 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/app/models/.gitkeep -------------------------------------------------------------------------------- /app/models/additions/ldap_authentication.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Adds LDAP-based authentication to the {User} model. Mixed in if this 16 | # Squash install is configured to use LDAP-based authentication. 17 | 18 | module LdapAuthentication 19 | extend ActiveSupport::Concern 20 | 21 | # @return [String] This user's LDAP distinguished name (DN). 22 | 23 | def distinguished_name 24 | "#{Squash::Configuration.authentication.ldap.search_key}=#{username},#{Squash::Configuration.authentication.ldap.tree_base}" 25 | end 26 | 27 | private 28 | 29 | def create_primary_email 30 | emails.create!(email: "#{username}@#{Squash::Configuration.mailer.domain}", primary: true) 31 | end 32 | end 33 | 34 | -------------------------------------------------------------------------------- /app/models/device_bug.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class DeviceBug < ActiveRecord::Base 16 | self.primary_keys = [:bug_id, :device_id] 17 | 18 | belongs_to :bug, inverse_of: :device_bugs 19 | 20 | validates :bug, 21 | presence: true 22 | validates :device_id, 23 | presence: true, 24 | length: {maximum: 126} 25 | end 26 | -------------------------------------------------------------------------------- /app/models/observers/comment_observer.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This observer on the {Comment} class creates the "comment" {Event} (on {Bug}) 16 | # as necessary. 17 | 18 | class CommentObserver < ActiveRecord::Observer 19 | # @private 20 | def after_create(comment) 21 | create_event comment 22 | watch_bug comment 23 | end 24 | 25 | # @private 26 | def after_commit_on_create(comment) 27 | BackgroundRunner.run CommentNotificationMailer, comment.id 28 | end 29 | 30 | private 31 | 32 | def create_event(comment) 33 | Event.create! do |event| 34 | event.bug_id = comment.bug_id 35 | event.kind = 'comment' 36 | event.data = {'comment_id' => comment.id} 37 | event.user_id = comment.user_id 38 | end 39 | end 40 | 41 | def watch_bug(comment) 42 | comment.user.watches.where(bug_id: comment.bug_id).find_or_create 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /app/models/observers/deploy_observer.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This observer on the {Deploy} model: 16 | # 17 | # * sets a Project's `uses_releases` attribute if the Deploy has release 18 | # information. 19 | 20 | class DeployObserver < ActiveRecord::Observer 21 | # @private 22 | def after_create(deploy) 23 | update_project_release_setting deploy 24 | end 25 | 26 | private 27 | 28 | def update_project_release_setting(deploy) 29 | return unless deploy.release? 30 | return if deploy.environment.project.uses_releases_override? 31 | deploy.environment.project.update_attribute :uses_releases, true 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/models/observers/occurrence_observer.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This observer on the {Occurrence} model: 16 | # 17 | # * sends an email when a Bug is critical, and 18 | # * creates {DeviceBug DeviceBugs} as necessary. 19 | 20 | class OccurrenceObserver < ActiveRecord::Observer 21 | # @private 22 | def after_commit_on_create(occurrence) 23 | # send emails 24 | BackgroundRunner.run OccurrenceNotificationMailer, occurrence.id 25 | 26 | # notify pagerduty 27 | BackgroundRunner.run PagerDutyNotifier, occurrence.id 28 | end 29 | 30 | # @private 31 | def after_create(occurrence) 32 | if occurrence.device_id.present? 33 | occurrence.bug.device_bugs.where(device_id: occurrence.device_id).find_or_create! 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /app/models/observers/watch_observer.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This observer pre-fills (or empties) a User's feed (stored in the 16 | # `user_events` table) when a User watches or unwatches a Bug. 17 | 18 | class WatchObserver < ActiveRecord::Observer 19 | # @private 20 | def after_create(watch) 21 | fill_feed watch 22 | end 23 | 24 | # @private 25 | def after_destroy(watch) 26 | empty_feed watch 27 | end 28 | 29 | private 30 | 31 | def fill_feed(watch) 32 | # add the bug's last 10 events to the user's feed 33 | UserEvent.connection.execute <<-SQL 34 | INSERT INTO user_events 35 | (user_id, event_id, created_at) 36 | SELECT #{watch.user_id}, id, created_at 37 | FROM events 38 | WHERE bug_id = #{watch.bug_id} 39 | ORDER BY created_at DESC 40 | LIMIT 10 41 | SQL 42 | end 43 | 44 | def empty_feed(watch) 45 | # remove all events from the user's feed pertaining to that bug 46 | UserEvent.connection.execute <<-SQL 47 | DELETE FROM user_events 48 | USING events 49 | WHERE user_events.event_id = events.id 50 | AND events.bug_id = #{watch.bug_id} 51 | AND user_events.user_id = #{watch.user_id} 52 | SQL 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /app/models/user_event.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Denormalized association between a {User} and the {Event Events} from the 16 | # {Bug Bugs} that that User is {Watch watching}. 17 | # 18 | # Associations 19 | # ============ 20 | # 21 | # | | | 22 | # |:--------|:----------------------------------------------| 23 | # | `user` | The {User} watching the Bug. | 24 | # | `event` | The {Event} for the Bug the User is watching. | 25 | 26 | class UserEvent < ActiveRecord::Base 27 | self.primary_keys = [:user_id, :event_id] 28 | 29 | belongs_to :user, inverse_of: :user_events 30 | belongs_to :event, inverse_of: :user_events 31 | 32 | validates :user, 33 | presence: true 34 | validates :event, 35 | presence: true 36 | end 37 | -------------------------------------------------------------------------------- /app/models/watch.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # An association created when a {User} watches a {Bug}. {Event Events} created 16 | # for that Bug will appear in the User's feed. 17 | # 18 | # Associations 19 | # ============ 20 | # 21 | # | | | 22 | # |:-------|:-----------------------------| 23 | # | `user` | The {User} watching the Bug. | 24 | # | `bug` | The {Bug} being watched. | 25 | 26 | class Watch < ActiveRecord::Base 27 | self.primary_keys = :user_id, :bug_id 28 | 29 | belongs_to :user, inverse_of: :watches 30 | belongs_to :bug, inverse_of: :watches 31 | 32 | validates :user, 33 | presence: true 34 | validates :bug, 35 | presence: true 36 | validate :user_cannot_watch_foreign_bug 37 | 38 | # @private 39 | def as_json(options=nil) 40 | options ||= {} 41 | options[:except] = Array.wrap(options[:except]) + [:user_id, :bug_id] 42 | options[:include] = Array.wrap(options[:include]) + [:user, :bug] 43 | super options 44 | end 45 | 46 | private 47 | 48 | def user_cannot_watch_foreign_bug 49 | errors.add(:bug_id, :no_permission) unless user.role(bug.environment.project) 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /app/views/notification_mailer/assign.text.erb: -------------------------------------------------------------------------------- 1 | <%= @assigner.try!(:name) || "Someone" %> has assigned bug #<%= @bug.number %> on <%= @bug.environment.project.name %> 2 | to you: 3 | 4 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 5 | 6 | Project: <%= @bug.environment.project.name %> 7 | Environment: <%= @bug.environment.name %> 8 | Revision: <%= @bug.revision %> 9 | Blamed Commit: <%= @bug.blamed_revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | ---- 21 | 22 | Is it your fault? 23 | 24 | Under "Management," assign it to yourself, then commit the fix. Mark the bug 25 | as fixed when the fix is pushed. 26 | 27 | Is it someone else's fault? 28 | 29 | Under "Management," assign it to that person -- they will receive an email 30 | notification. 31 | 32 | Is this not really a bug? 33 | 34 | Under "Management," mark the bug as "no one will fix this." You will no 35 | longer receive notifications about this non-bug. You can also simply delete 36 | the bug if it was a one-time test. 37 | 38 | You should take one of the above three actions -- don't just let the bug sit 39 | there! 40 | 41 | Yours truly, 42 | Squash 43 | 44 | --- 45 | 46 | If you wish to stop receiving these emails, visit your account page: 47 | <%= account_url %> 48 | -------------------------------------------------------------------------------- /app/views/notification_mailer/blame.text.erb: -------------------------------------------------------------------------------- 1 | A new exception has occurred on <%= @bug.environment.project.name %>, and Squash 2 | suspects that it's your fault. 3 | 4 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 5 | 6 | Project: <%= @bug.environment.project.name %> 7 | Environment: <%= @bug.environment.name %> 8 | Revision: <%= @bug.revision %> 9 | Blamed Commit: <%= @bug.blamed_revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | ---- 21 | 22 | Is it your fault? 23 | 24 | Under "Management," assign it to yourself, then commit the fix. Mark the bug 25 | as fixed when the fix is pushed. 26 | 27 | Is it someone else's fault? 28 | 29 | Under "Management," assign it to that person -- they will receive an email 30 | notification. 31 | 32 | Is this not really a bug? 33 | 34 | Under "Management," mark the bug as "no one will fix this." You will no 35 | longer receive notifications about this non-bug. You can also simply delete 36 | the bug if it was a one-time test. 37 | 38 | You should take one of the above three actions -- don't just let the bug sit 39 | there! 40 | 41 | ---- 42 | 43 | <% if @bug.occurrences.first %> 44 | 45 | Stack trace of initial occurrence: 46 | 47 | <%= render_backtrace(@bug.occurrences.first.faulted_backtrace).indent(2) %> 48 | 49 | ---- 50 | <% end %> 51 | 52 | Yours truly, 53 | Squash 54 | -------------------------------------------------------------------------------- /app/views/notification_mailer/comment.text.erb: -------------------------------------------------------------------------------- 1 | <%= @comment.user.name %> has commented on this bug: 2 | 3 | <%= @bug.class_name %> 4 | <% if @bug.special_file? %> 5 | in <%= @bug.file %> 6 | <% else %> 7 | in <%= @bug.file %>:<%= @bug.line %> 8 | <% end %> 9 | 10 | <%= @bug.message_template %> 11 | 12 | His/her comment was: 13 | 14 | <%= email_quote @comment.body %> 15 | 16 | More details at <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug, anchor: 'comments' %> 17 | 18 | Yours truly, 19 | Squash 20 | --- 21 | 22 | If you wish to stop receiving these emails, visit your account page: 23 | <%= account_url %> 24 | -------------------------------------------------------------------------------- /app/views/notification_mailer/critical.text.erb: -------------------------------------------------------------------------------- 1 | Bug #<%= @bug.number %> on <%= @bug.environment.project.name %> is occurring 2 | a lot. Perhaps someone should look into it. 3 | 4 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 5 | 6 | Project: <%= @bug.environment.project.name %> 7 | Environment: <%= @bug.environment.name %> 8 | Revision: <%= @bug.revision %> 9 | 10 | <%= @bug.class_name %> 11 | <% if @bug.special_file? %> 12 | in <%= @bug.file %> 13 | <% else %> 14 | in <%= @bug.file %>:<%= @bug.line %> 15 | <% end %> 16 | 17 | <%= @bug.message_template %> 18 | 19 | Yours truly, 20 | Squash 21 | -------------------------------------------------------------------------------- /app/views/notification_mailer/deploy.text.erb: -------------------------------------------------------------------------------- 1 | The fix for this bug has just been deployed: 2 | 3 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 4 | 5 | Project: <%= @bug.environment.project.name %> 6 | Environment: <%= @bug.environment.name %> 7 | Revision: <%= @bug.revision %> 8 | Blamed Commit: <%= @bug.blamed_revision %> 9 | Fix Commit: <%= @bug.resolution_revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | Yours truly, 21 | Squash 22 | -------------------------------------------------------------------------------- /app/views/notification_mailer/initial.text.erb: -------------------------------------------------------------------------------- 1 | There's a new class of exceptions occurring on <%= @bug.environment.project.name %>: 2 | 3 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 4 | 5 | Project: <%= @bug.environment.project.name %> 6 | Environment: <%= @bug.environment.name %> 7 | Revision: <%= @bug.revision %> 8 | 9 | <%= @bug.class_name %> 10 | <% if @bug.special_file? %> 11 | in <%= @bug.file %> 12 | <% else %> 13 | in <%= @bug.file %>:<%= @bug.line %> 14 | <% end %> 15 | 16 | <%= @bug.message_template %> 17 | 18 | <% if @bug.occurrences.first %> 19 | ---- 20 | 21 | Stack trace of initial occurrence: 22 | 23 | <%= render_backtrace(@bug.occurrences.first.faulted_backtrace).indent(2) %> 24 | 25 | ---- 26 | <% end %> 27 | 28 | Yours truly, 29 | Squash 30 | -------------------------------------------------------------------------------- /app/views/notification_mailer/occurrence.text.erb: -------------------------------------------------------------------------------- 1 | There has been a new occurrence of this bug. 2 | 3 | Bug: <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 4 | Occurrence: <%= project_environment_bug_occurrence_url @bug.environment.project, @bug.environment, @bug, @occurrence %> 5 | 6 | THE BUG 7 | 8 | <%= @bug.class_name %> 9 | <% if @bug.special_file? %> 10 | in <%= @bug.file %> 11 | <% else %> 12 | in <%= @bug.file %>:<%= @bug.line %> 13 | <% end %> 14 | 15 | THE OCCURRENCE 16 | 17 | <%= @occurrence.message %> 18 | 19 | <% if @occurrence.web? %> 20 | <% if @occurrence.url %> 21 | Request: <%= @occurrence.request_method %> <%= @occurrence.url.to_s %> 22 | <% else %> 23 | Request: <%= @occurrence.request_method %> (invalid URL) 24 | <% end %> 25 | <% end %> 26 | <% if @occurrence.rails? %> 27 | Controller: <%= @occurrence.controller %> 28 | Action: <%= @occurrence.action %> 29 | <% end %> 30 | <% if @occurrence.server? %> 31 | Hostname: <%= @occurrence.hostname %> 32 | PID: <%= @occurrence.pid %> 33 | <% end %> 34 | <% if @occurrence.client? %> 35 | Build: <%= @occurrence.build %> 36 | Device: <%= @occurrence.device_type %> 37 | OS: <%= @occurrence.operating_system %> 38 | <% end %> 39 | <% if @occurrence.mobile? %> 40 | Network Operator: <%= @occurrence.network_operator %> 41 | Network Type: <%= @occurrence.network_type %> 42 | <% end %> 43 | <% if @occurrence.browser? %> 44 | Web Browser: <%= @occurrence.browser_name %> (<%= @occurrence.browser_version %>) 45 | <% end %> 46 | 47 | Stack trace: 48 | 49 | <%= render_backtrace(@occurrence.faulted_backtrace).indent(2) %> 50 | 51 | Yours truly, 52 | Squash 53 | --- 54 | 55 | If you wish to stop receiving these emails, visit the bug page: 56 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug, anchor: 'notifications' %> 57 | -------------------------------------------------------------------------------- /app/views/notification_mailer/reopened.text.erb: -------------------------------------------------------------------------------- 1 | An exception on <%= @bug.environment.project.name %> has reopened this bug, 2 | which was previously marked as fixed and deployed: 3 | 4 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 5 | 6 | Project: <%= @bug.environment.project.name %> 7 | Environment: <%= @bug.environment.name %> 8 | Revision: <%= @bug.revision %> 9 | Fix Commit: <%= @bug.resolution_revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | You should revisit the bug and make sure that it was actually fixed. If an 21 | additional fix is required, update the fix commit under the Management page. 22 | 23 | Yours truly, 24 | Squash 25 | -------------------------------------------------------------------------------- /app/views/notification_mailer/resolved.text.erb: -------------------------------------------------------------------------------- 1 | <%= @resolver.try!(:name) || "Someone" %> has <%= @bug.fixed? ? "resolved a bug" : "marked a bug as irrelevant" %> 2 | that you were assigned to: 3 | 4 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 5 | 6 | Project: <%= @bug.environment.project.name %> 7 | Environment: <%= @bug.environment.name %> 8 | Revision: <%= @bug.revision %> 9 | Blamed Commit: <%= @bug.blamed_revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | Yours truly, 21 | Squash 22 | --- 23 | 24 | If you wish to stop receiving these emails, visit your account page: 25 | <%= account_url %> 26 | -------------------------------------------------------------------------------- /app/views/notification_mailer/threshold.text.erb: -------------------------------------------------------------------------------- 1 | Bug #<%= @bug.number %> on <%= @bug.environment.project.name %> has been 2 | occurring frequently lately. You set a threshold on how often it should occur, 3 | and this threshold was exceeded. 4 | 5 | <%= project_environment_bug_url @bug.environment.project, @bug.environment, @bug %> 6 | 7 | Project: <%= @bug.environment.project.name %> 8 | Environment: <%= @bug.environment.name %> 9 | Revision: <%= @bug.revision %> 10 | 11 | <%= @bug.class_name %> 12 | <% if @bug.special_file? %> 13 | in <%= @bug.file %> 14 | <% else %> 15 | in <%= @bug.file %>:<%= @bug.line %> 16 | <% end %> 17 | 18 | <%= @bug.message_template %> 19 | 20 | Yours truly, 21 | Squash 22 | -------------------------------------------------------------------------------- /app/views/occurrences/show.js.erb: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Square Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | $(document).ready(function() { 16 | $('#first-occurrence').liveUpdate(); 17 | $('#occurred-at').liveUpdate(); 18 | 19 | $('.complex-object').valueInspector(); 20 | 21 | $('.show-library-files').click(function(e) { 22 | $(e.currentTarget).parent().parent().find('li.lib, li.filtered').slideToggle(); 23 | }); 24 | 25 | $('.backtrace-link').click(function(event) { 26 | $($(event.target).attr('href')).slideToggle(); 27 | return false; 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /app/views/project/membership/edit.js.erb: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Square Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | $(document).ready(function() { 16 | new EmailAliasForm($('#email-aliases'), 17 | "<%= project_my_membership_emails_url format: 'json' %>", 18 | "<%= project_my_membership_emails_url format: 'json' %>"); 19 | }); 20 | -------------------------------------------------------------------------------- /app/views/projects/edit.js.erb: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Square Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | $(document).ready(function() { 16 | new MemberPanel($('#members'), 17 | "<%= escape_javascript @project.name %>", 18 | "<%= @project.to_param %>", 19 | "<%= users_url %>", 20 | "<%= project_memberships_url(@project, format: 'json') %>", 21 | "<%= project_membership_url(@project, 'USERID', format: 'json') %>", 22 | "<%= project_url(@project, format: 'json') %>", 23 | "<%= current_user.role(@project).to_s %>", 24 | false); 25 | 26 | $('#insert-prefab').click(function() { 27 | var lines; 28 | var prefabMenu = $('#prefab'); 29 | 30 | switch(prefabMenu.val()) { 31 | case 'rails': 32 | lines = ["vendor/"]; 33 | break; 34 | default: lines = []; 35 | } 36 | 37 | if (lines) 38 | $('#project_filter_paths_string').val(($('#project_filter_paths_string').val() + "\n" + lines.join("\n")).replace(/^\n/, '')); 39 | 40 | prefabMenu.val(''); 41 | 42 | return false; 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /app/views/users/show.html.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | # Copyright 2014 Square Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | require Rails.root.join('app', 'views', 'layouts', 'application.html.rb') 18 | 19 | module Views 20 | # @private 21 | module Users 22 | # @private 23 | class Show < Views::Layouts::Application 24 | needs :user 25 | 26 | protected 27 | 28 | def page_title() @user.name end 29 | 30 | def body_content 31 | full_width_section do 32 | h1 do 33 | image_tag @user.gravatar 34 | text @user.name 35 | end 36 | 37 | user_info 38 | end 39 | end 40 | 41 | private 42 | 43 | def user_info 44 | dl do 45 | dt "Username" 46 | dd @user.username 47 | dt "Joined" 48 | dd l(@user.created_at, format: :short_date) 49 | dt "Projects" 50 | dd @user.memberships.count 51 | dt "Projects Owned" 52 | dd @user.owned_projects.count 53 | end 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 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 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file is used by Rack-based servers to start the application. 16 | 17 | require ::File.expand_path('../config/environment', __FILE__) 18 | run Squash::Application 19 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Set up gems listed in the Gemfile. 16 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 17 | 18 | require 'bundler/setup' # Set up gems listed in the Gemfile. 19 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: postgresql 3 | encoding: utf8 4 | host: localhost 5 | username: squash 6 | password: 7 | database: squash_development 8 | 9 | test: 10 | adapter: postgresql 11 | encoding: utf8 12 | host: localhost 13 | username: squash 14 | password: 15 | database: squash_test 16 | 17 | production: 18 | adapter: postgresql 19 | encoding: utf8 20 | host: localhost 21 | username: squash 22 | password: 23 | database: squash_production 24 | pool: 30 25 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Load the Rails application. 16 | require File.expand_path('../application', __FILE__) 17 | 18 | # Initialize the Rails application. 19 | Rails.application.initialize! 20 | -------------------------------------------------------------------------------- /config/environments/common/activerecord.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cursors: false 3 | -------------------------------------------------------------------------------- /config/environments/common/authentication.yml: -------------------------------------------------------------------------------- 1 | --- 2 | strategy: password 3 | registration_enabled: true 4 | -------------------------------------------------------------------------------- /config/environments/common/dogfood.yml: -------------------------------------------------------------------------------- 1 | transmit_timeout: 60 2 | ignored_exception_classes: 3 | - ActionController::RoutingError 4 | - ActionController::MethodNotAllowed 5 | - ActionController::ActionNotFound 6 | ignored_exception_messages: 7 | SignalException: 8 | - SIGTERM 9 | "ActiveRecord::StatementInvalid": 10 | - This connection has been closed. 11 | failsafe_log: log/squash.failsafe.log 12 | disabled: true 13 | allowed_origins: [] -------------------------------------------------------------------------------- /config/environments/common/javascript_dogfood.yml: -------------------------------------------------------------------------------- 1 | --- {} 2 | -------------------------------------------------------------------------------- /config/environments/common/jira.yml: -------------------------------------------------------------------------------- 1 | --- 2 | disabled: true 3 | authentication: 4 | strategy: basic 5 | user: YOUR_USERNAME 6 | password: YOUR_PASSWORD 7 | api_host: "https://yourcompany.com" 8 | api_root: "/jira" 9 | create_issue_details: "/secure/CreateIssueDetails!init.jspa" 10 | -------------------------------------------------------------------------------- /config/environments/common/mailer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | from: squash@YOUR_DOMAIN 3 | domain: YOUR_DOMAIN 4 | strategy: sendmail 5 | smtp_settings: 6 | address: 7 | port: 8 | domain: 9 | user_name: 10 | password: 11 | authentication: 12 | enable_starttls_auto: 13 | -------------------------------------------------------------------------------- /config/environments/common/pagerduty.yml: -------------------------------------------------------------------------------- 1 | --- 2 | disabled: true 3 | authentication: 4 | strategy: token 5 | token: YOUR_AUTH_TOKEN 6 | api_url: "https://events.pagerduty.com/generic/2010-04-15/create_event.json" 7 | -------------------------------------------------------------------------------- /config/environments/common/repositories.yml: -------------------------------------------------------------------------------- 1 | --- 2 | directory: tmp/repos 3 | -------------------------------------------------------------------------------- /config/environments/development/dogfood.yml: -------------------------------------------------------------------------------- 1 | --- 2 | disabled: true 3 | -------------------------------------------------------------------------------- /config/environments/development/mailer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_url_options: 3 | host: "localhost:3000" 4 | protocol: http 5 | -------------------------------------------------------------------------------- /config/environments/production/dogfood.yml: -------------------------------------------------------------------------------- 1 | --- 2 | disabled: true 3 | api_key: YOUR_PRODUCTION_SQUASH_API_KEY 4 | api_host: YOUR_URL 5 | -------------------------------------------------------------------------------- /config/environments/production/javascript_dogfood.yml: -------------------------------------------------------------------------------- 1 | --- 2 | APIHost: YOUR_URL 3 | -------------------------------------------------------------------------------- /config/environments/production/mailer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_url_options: 3 | host: YOUR_HOSTNAME 4 | protocol: https 5 | -------------------------------------------------------------------------------- /config/environments/test/dogfood.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exception_behavior_when_disabled: raise 3 | -------------------------------------------------------------------------------- /config/environments/test/jira.yml: -------------------------------------------------------------------------------- 1 | --- 2 | authentication: 3 | password: obfuscated 4 | -------------------------------------------------------------------------------- /config/environments/test/mailer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_url_options: 3 | host: "test.host" 4 | protocol: http 5 | -------------------------------------------------------------------------------- /config/environments/test/people.yml: -------------------------------------------------------------------------------- 1 | --- 2 | url: 3 | -------------------------------------------------------------------------------- /config/environments/test/squash_javascript.yml: -------------------------------------------------------------------------------- 1 | --- 2 | disabled: true 3 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | Rails.application.config.assets.precompile << 'flot/excanvas.js' 12 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 18 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 19 | 20 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 21 | # Rails.backtrace_cleaner.remove_silencers! 22 | -------------------------------------------------------------------------------- /config/initializers/concurrency.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Spawn and stop the thread pool 16 | 17 | if defined?(PhusionPassenger) 18 | PhusionPassenger.on_event(:starting_worker_process) do |forked| 19 | Multithread.start 20 | end 21 | 22 | PhusionPassenger.on_event(:stopping_worker_process) do 23 | Multithread.stop 24 | end 25 | elsif defined?(Unicorn) 26 | Unicorn::HttpServer.class_eval do 27 | old = instance_method(:worker_loop) 28 | define_method(:worker_loop) do |worker| 29 | Multithread.start 30 | old.bind(self).call(worker) 31 | end 32 | end 33 | else 34 | # Not in Passenger at all 35 | Multithread.start 36 | at_exit { Multithread.stop } 37 | end 38 | 39 | # Load concurrency setup 40 | 41 | BackgroundRunner.runner.setup if BackgroundRunner.runner.respond_to?(:setup) 42 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :marshal 4 | -------------------------------------------------------------------------------- /config/initializers/field_error_proc.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Change the behavior of fields with bad data. This wraps them in a span with 16 | # data-errors attributes listing the errors. JavaScript then creates the 17 | # appropriate visual error display. 18 | 19 | ActionView::Base.field_error_proc = Proc.new do |html, object| 20 | errors = Array.wrap(object.error_message).map { |error| %(data-error="#{error}") }.join(' ') 21 | %(#{html}).html_safe 22 | end 23 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | # Configure sensitive parameters which will be filtered from the log file. 18 | Rails.application.config.filter_parameters += [:password] 19 | -------------------------------------------------------------------------------- /config/initializers/html5.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Adds HTML5 support to Erector::Widget. 16 | 17 | class Erector::Widget 18 | tag 'summary' 19 | end 20 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | ActiveSupport::Inflector.inflections do |inflect| 18 | inflect.singular 'statuses', 'status' 19 | end 20 | -------------------------------------------------------------------------------- /config/initializers/jira.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | # Copyright 2014 Square Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # @private 18 | module JIRA 19 | 20 | # @private 21 | # 22 | # Adds timeout capability to the JIRA HTTP client. 23 | 24 | class HttpClient 25 | def http_conn_with_timeout(*args) 26 | http_conn = http_conn_without_timeout(*args) 27 | http_conn.open_timeout = @options[:open_timeout] 28 | http_conn.read_timeout = @options[:read_timeout] 29 | http_conn 30 | end 31 | alias_method_chain :http_conn, :timeout 32 | end 33 | end unless Squash::Configuration.jira.disabled? 34 | -------------------------------------------------------------------------------- /config/initializers/load_autoload_paths.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Not sure why this isn't done automatically by Jetty/Jetpack, but oh well. 16 | 17 | if Squash::Application.config.cache_classes 18 | Squash::Application.config.autoload_paths.each do |path| 19 | Dir.glob(path.join('**', '*.rb')).each { |file| require file } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /config/initializers/mail.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Configure ActionMailer 16 | 17 | if Squash::Configuration.mailer.strategy == 'smtp' 18 | ActionMailer::Base.smtp_settings = Squash::Configuration.mailer.smtp_settings.symbolize_keys 19 | end 20 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | # Add new mime types for use in respond_to blocks: 18 | # Mime::Type.register "text/richtext", :rtf 19 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | # Your secret key is used for verifying the integrity of signed cookies. 18 | # If you change this key, all old signed cookies will become invalid! 19 | 20 | # Make sure the secret is at least 30 characters and all random, 21 | # no regular words or you'll be exposed to dictionary attacks. 22 | # You can use `rake secret` to generate a secure secret key. 23 | 24 | # Make sure your secret_key_base is kept private 25 | # if you're sharing your code publicly. 26 | Squash::Application.config.secret_key_base = '_SECRET_' 27 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | Rails.application.config.session_store :cookie_store, key: '_squash_session' 18 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Be sure to restart your server when you modify this file. 16 | 17 | # This file contains settings for ActionController::ParamsWrapper which 18 | # is enabled by default. 19 | 20 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 21 | ActiveSupport.on_load(:action_controller) do 22 | wrap_parameters format: [] 23 | end 24 | 25 | # To enable root element in JSON for ActiveRecord objects. 26 | # ActiveSupport.on_load(:active_record) do 27 | # self.include_root_in_json = true 28 | # end 29 | -------------------------------------------------------------------------------- /config/preinitializers/jruby.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # JRUBY-6389 16 | 17 | if RUBY_PLATFORM == 'java' 18 | require 'pathname' 19 | 20 | Pathname.class_eval do 21 | def to_str() to_s end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /config/preinitializers/safe_yaml.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Let's make SafeYAML act exactly like YAML by default, to avoid surprising 16 | # behavior. 17 | SafeYAML::OPTIONS[:default_mode] = :unsafe 18 | SafeYAML::OPTIONS[:deserialize_symbols] = true 19 | 20 | # And let's whitelist the things we transmit over YAML 21 | SafeYAML.whitelist! Squash::Java::Namespace 22 | -------------------------------------------------------------------------------- /config/preinitializers/source_maps.rb: -------------------------------------------------------------------------------- 1 | # Ugh. The sourcemap gem defines a module called SourceMap, which shares the name 2 | # of one of our models. So we have to rename it before we load our model. 3 | if ::SourceMap.kind_of?(Module) 4 | ::GemSourceMap = ::SourceMap 5 | Object.send :remove_const, :SourceMap 6 | elsif ::SourceMap.kind_of?(Class) 7 | raise "SourceMap (the model) defined prior to SourceMap (the module) -- see application.rb" 8 | else 9 | raise "SourceMap must be defined -- see application.rb" 10 | end 11 | 12 | # and redefine the methods that use the other SourceMap class 13 | 14 | # @private 15 | class Sprockets::Asset 16 | def sourcemap 17 | relative_path = if pathname.to_s.include?(Rails.root.to_s) 18 | pathname.relative_path_from(Rails.root) 19 | else 20 | pathname 21 | end.to_s 22 | # any extensions after the ".js" can be removed, because they will have 23 | # already been processed 24 | relative_path.gsub! /(?<=\.js)\..*$/, '' 25 | resource_path = [Rails.application.config.assets.prefix, logical_path].join('/') 26 | 27 | mappings = Array.new 28 | to_s.lines.each_with_index do |_, index| 29 | offset = GemSourceMap::Offset.new(index, 0) 30 | mappings << GemSourceMap::Mapping.new(relative_path, offset, offset) 31 | end 32 | GemSourceMap::Map.new(mappings, resource_path) 33 | end 34 | end 35 | 36 | # @private 37 | class Sprockets::BundledAsset < Sprockets::Asset 38 | def sourcemap 39 | to_a.inject(GemSourceMap::Map.new) do |map, asset| 40 | map + asset.sourcemap 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /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 `rake 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: fd1028c1545b8d18bbc63f01c09d98d825002a4c92f275542dc10061b32b5730ca5d1b56a84e9441c23ee5e610365fd923e0a1c594f31915aefadacce67da213 15 | 16 | test: 17 | secret_key_base: 4274eb8fc145b1b8c2b1a461b5a00cd21d96197d8cbefcecf8fd8cada868fdc3e76c8ba814b76ec943280229406b623092a889226671c850b56778b0ff569c9e 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 | -------------------------------------------------------------------------------- /data/brushes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | by_extension: 3 | .ant: xml 4 | .applejs: javascript 5 | .as: actionscript3 6 | .as3: actionscript3 7 | .atom: xml 8 | .atom.erb: ! 'ruby; html-script: true' 9 | .bash: shell 10 | .builder: ruby 11 | .c: cpp 12 | .cc: cpp 13 | .cf: coldfusion 14 | .cpp: cpp 15 | .cs: c-sharp 16 | .css: css 17 | .diff: diff 18 | .erl: erlang 19 | .es: actionscript3 20 | .fx: javafx 21 | .gemspec: ruby 22 | .groovy: groovy 23 | .h: obj-c 24 | .hpp: cpp 25 | .htm: xml 26 | .html: xml 27 | .html.erb: ! 'ruby; html-script: true' 28 | .java: java 29 | .jnlp: xml 30 | .jruby: ruby 31 | .js: javascript 32 | .js2: actionscript3 33 | .json: javascript 34 | .m: obj-c 35 | .pas: delphi 36 | .patch: diff 37 | .pch: obj-c 38 | .php: ! 'php; html-script: true' 39 | .pl: perl 40 | .pm: perl 41 | .ps: powershell 42 | .py: python 43 | .rake: ruby 44 | .rb: ruby 45 | .rhtml: ! 'ruby; html-script: true' 46 | .rjs: ruby 47 | .rss: xml 48 | .rss.erb: ! 'ruby; html-script: true' 49 | .ru: ruby 50 | .rxml: ruby 51 | .sass: sass 52 | .scala: scala 53 | .scpt: applescript 54 | .scss: sass 55 | .sh: shell 56 | .shtm: xml 57 | .shtml: xml 58 | .sql: sql 59 | .vb: vb 60 | .wsdl: xml 61 | .xml: xml 62 | .xml.erb: ! 'ruby; html-script: true' 63 | .xsl: xml 64 | .xslt: xml 65 | .yaml: yaml 66 | .yml: yaml 67 | by_filename: 68 | Capfile: ruby 69 | Gemfile: ruby 70 | Rakefile: ruby 71 | default: plain 72 | -------------------------------------------------------------------------------- /db/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite3 -------------------------------------------------------------------------------- /db/migrate/20130125021927_index_occurrences_by_bug_and_redirected.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class IndexOccurrencesByBugAndRedirected < ActiveRecord::Migration 16 | def up 17 | execute "CREATE INDEX occurrences_bug_redirect ON occurrences(bug_id, redirect_target_id)" 18 | end 19 | 20 | def down 21 | execute "DROP INDEX occurrences_bug_redirect" 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /db/migrate/20130131002503_track_bugs_per_device.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class TrackBugsPerDevice < ActiveRecord::Migration 16 | def up 17 | execute <<-SQL 18 | CREATE TABLE device_bugs ( 19 | bug_id INTEGER NOT NULL REFERENCES bugs(id) ON DELETE CASCADE, 20 | device_id CHARACTER VARYING(126) NOT NULL, 21 | PRIMARY KEY (bug_id, device_id) 22 | ) 23 | SQL 24 | end 25 | 26 | def down 27 | drop_table :device_bugs 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20130215185809_fix_condition_on_rule_occurrences_set_latest.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class FixConditionOnRuleOccurrencesSetLatest < ActiveRecord::Migration 16 | def up 17 | execute <<-SQL 18 | CREATE OR REPLACE RULE occurrences_set_latest AS 19 | ON INSERT TO occurrences DO 20 | UPDATE bugs 21 | SET latest_occurrence = NEW.occurred_at 22 | WHERE (bugs.id = NEW.bug_id) 23 | AND ((bugs.latest_occurrence IS NULL) 24 | OR (bugs.latest_occurrence < NEW.occurred_at)) 25 | SQL 26 | end 27 | 28 | def down 29 | execute <<-SQL 30 | CREATE OR REPLACE RULE occurrences_set_latest AS 31 | ON INSERT TO occurrences DO 32 | UPDATE bugs 33 | SET latest_occurrence = NEW.occurred_at 34 | WHERE (bugs.id = NEW.bug_id) 35 | AND (bugs.latest_occurrence IS NULL) 36 | OR (bugs.latest_occurrence < NEW.occurred_at) 37 | SQL 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /db/migrate/20130221020818_create_blames.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class CreateBlames < ActiveRecord::Migration 16 | def up 17 | execute <<-SQL 18 | CREATE UNLOGGED TABLE blames ( 19 | id SERIAL PRIMARY KEY, 20 | repository_hash CHARACTER(40) NOT NULL, 21 | revision CHARACTER(40) NOT NULL, 22 | file CHARACTER VARYING(255) NOT NULL CHECK (CHAR_LENGTH(file) > 0), 23 | line INTEGER NOT NULL CHECK (line > 0), 24 | blamed_revision CHARACTER VARYING(40) NOT NULL, 25 | updated_at TIMESTAMP WITHOUT TIME ZONE 26 | ) 27 | SQL 28 | 29 | execute "CREATE UNIQUE INDEX blames_key ON blames(repository_hash, revision, file, line)" 30 | execute "CREATE UNIQUE INDEX blames_lru ON blames(updated_at)" 31 | end 32 | 33 | def down 34 | drop_table :blames 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /db/migrate/20130222055524_fix_blame_lru_key.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class FixBlameLruKey < ActiveRecord::Migration 16 | def up 17 | execute "DROP INDEX blames_lru" 18 | execute "CREATE INDEX blames_lru ON blames(updated_at)" 19 | end 20 | 21 | def down 22 | execute "DROP INDEX blames_lru" 23 | execute "CREATE UNIQUE INDEX blames_lru ON blames(updated_at)" 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20140130012355_add_mapping_to_source_map.rb: -------------------------------------------------------------------------------- 1 | class AddMappingToSourceMap < ActiveRecord::Migration 2 | def up 3 | execute <<-SQL 4 | ALTER TABLE source_maps 5 | ADD COLUMN "from" CHARACTER VARYING(24) NOT NULL DEFAULT 'minified' CHECK (CHAR_LENGTH("from") > 0), 6 | ADD COLUMN "to" CHARACTER VARYING(24) NOT NULL DEFAULT 'original' CHECK (CHAR_LENGTH("to") > 0) 7 | SQL 8 | 9 | execute 'ALTER TABLE source_maps ALTER "from" DROP NOT NULL' 10 | execute 'ALTER TABLE source_maps ALTER "to" DROP NOT NULL' 11 | execute "DROP INDEX source_maps_env_revision" 12 | execute 'CREATE INDEX source_maps_env_revision ON source_maps(environment_id, revision, "from")' 13 | end 14 | 15 | def down 16 | execute 'ALTER TABLE source_maps DROP "from", DROP "to"' 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20151126022941_add_hosted_filename_to_source_maps.rb: -------------------------------------------------------------------------------- 1 | class AddHostedFilenameToSourceMaps < ActiveRecord::Migration 2 | def up 3 | add_column :source_maps, :filename, :string, limit: 255 4 | 5 | say "Updating existing source maps" 6 | SourceMap.reset_column_information 7 | SourceMap.find_each(batch_size: 50) do |map| 8 | map.update_attribute :filename, map.map.filename 9 | end 10 | 11 | change_column :source_maps, :filename, :string, null: false, limit: 255 12 | 13 | add_index :source_maps, :filename 14 | end 15 | 16 | def down 17 | remove_column :source_maps, :filename 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file should contain all the record creation needed to seed the database with its default values. 16 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 17 | # 18 | # Examples: 19 | # 20 | # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) 21 | # Mayor.create(:name => 'Emanuel', :city => cities.first) 22 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | js 3 | -------------------------------------------------------------------------------- /doc/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | If you would like to contribute code to Squash, thank you! You can do so through 5 | GitHub by forking one of the repositories and sending a pull request. However, 6 | before your code can be accepted into the project we need you to sign the (super 7 | simple) [Individual Contributor License Agreement (CLA)][1]. 8 | 9 | [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1 10 | -------------------------------------------------------------------------------- /doc/fdoc/deobfuscation-POST.fdoc: -------------------------------------------------------------------------------- 1 | --- 2 | description: | 3 | Upload Java deobfuscation data to Squash. This data typically comes from a 4 | renamelog.xml file generated by yGuard, and is parsed and serialized using the 5 | `squash_java_deobfuscator` gem. 6 | responseCodes: 7 | - status: 422 8 | successful: false 9 | description: | 10 | * Invalid deobfuscation data was provided. 11 | * Missing required API parameter. 12 | - status: 403 13 | successful: false 14 | description: Unknown API key. 15 | - status: 404 16 | successful: false 17 | description: | 18 | * Unknown build number. 19 | * Unknown environment name. 20 | - status: 201 21 | successful: true 22 | requestParameters: 23 | properties: 24 | namespace: 25 | description: | 26 | The `Squash::Java::Namespace` object (generated using the 27 | `squash_java_deobfuscator` gem), YAML-serialized, then gzipped, then base 28 | 64-encoded. 29 | required: true 30 | type: string 31 | example: "eJxj4ci3kgouLE0szvBKLEu0svJLzE0tLkhMTmW3EnAoKMrMzSzJLEstzrfi\nCE4tYbPicsgAKq1msBJ2ACrKTkxPjS/Kzy8pzrdmZ7PmqGYAABwOGY8=\n" 32 | api_key: 33 | description: Your project's API key. 34 | required: true 35 | type: string 36 | example: 22c09d74-1882-4029-9699-af4c57ed060c 37 | environment: 38 | description: The environment name. 39 | required: true 40 | type: string 41 | example: production 42 | build: 43 | description: | 44 | The internal build number of the release this deobfuscation data 45 | pertains to. 46 | required: true 47 | type: string 48 | example: '6314' 49 | -------------------------------------------------------------------------------- /doc/fdoc/sourcemap-POST.fdoc: -------------------------------------------------------------------------------- 1 | --- 2 | description: | 3 | Uploads a JavaScript source map to Squash. This data is generated by your 4 | JavaScript minifier, and then parsed and serialized using the 5 | `squash_javascript` gem. 6 | responseCodes: 7 | - status: 422 8 | successful: false 9 | description: | 10 | * Missing required parameter. 11 | * Invalid parameter value. 12 | - status: 403 13 | successful: false 14 | description: Unknown API key. 15 | - status: 201 16 | successful: true 17 | requestParameters: 18 | properties: 19 | sourcemap: 20 | description: | 21 | A JSON-serialized source map, gzipped, then base 64-encoded. 22 | required: true 23 | type: string 24 | example: "eJxj4ci3UgguLE0szvBKLEssTi7KLCixsgrOLy1KTvVNLGCz4nPITSwoyMxL\nL45mAABqrw+t\n" 25 | api_key: 26 | description: Your project's API key. 27 | required: true 28 | type: string 29 | example: b305d2a6-dc2a-4c01-a345-82e8ce529c26 30 | environment: 31 | description: The name of the environment to which this source map applies. 32 | required: true 33 | type: string 34 | example: production 35 | revision: 36 | description: | 37 | The SHA1 of the Git revision of the code under which this source map was 38 | generated. 39 | required: true 40 | type: string 41 | example: 2dc20c984283bede1f45863b8f3b4dd9b5b554cc 42 | from: 43 | description: | 44 | The type of generated JavaScript code this source map transforms from. 45 | "hosted" should be used for the final hosted JS; other names are 46 | arbitrary. 47 | required: true 48 | type: string 49 | example: hosted 50 | to: 51 | description: | 52 | The type of generated or human-written JavaScript/CoffeeScript code this 53 | source map transforms to. 54 | required: true 55 | type: string 56 | example: concatenated 57 | -------------------------------------------------------------------------------- /doc/fdoc/squash.fdoc.service: -------------------------------------------------------------------------------- 1 | --- 2 | name: Squash 3 | basePath: '/api/1.0' 4 | description: | 5 | The API for Squash allows client libraries to notify Squash of exceptions and 6 | deploys, and upload data that Squash can use to analyze incoming exceptions 7 | (e.g., source maps, symbolication data, etc.). 8 | -------------------------------------------------------------------------------- /doc/fdoc/symbolication-POST.fdoc: -------------------------------------------------------------------------------- 1 | --- 2 | description: | 3 | Upload Objective-C symbolication data to Squash. This data is generated by 4 | your compiler, and then uploaded to Squash using the `squash_ios_symbolicator` 5 | gem. 6 | responseCodes: 7 | - status: 422 8 | successful: false 9 | description: | 10 | * Missing required parameter. 11 | * Invalid symbolication data. 12 | - status: 201 13 | successful: true 14 | requestParameters: 15 | properties: 16 | symbolications: 17 | description: Array of symbolication data. 18 | required: true 19 | type: array 20 | items: 21 | type: hash 22 | properties: 23 | uuid: 24 | description: | 25 | The unique symbolication UUID. This UUID is generated by DWARF for 26 | each new compile, and can be found using `dwarfdump -u`. 27 | required: true 28 | type: string 29 | example: 8817e7da-8c0d-44f0-9eec-24e418425630 30 | symbols: 31 | description: | 32 | A `Squash::Symbolicator::Symbols` object (as generated by 33 | `squash_ios_symbolicator`), YAML-serialized, then gzipped, then base 34 | 64-encoded. 35 | required: false 36 | type: string 37 | example: "eJxj4ci3kgquzE3Kz8lMTizJL7KygvCK2ax4HYohzGgGAP7YDRY=\n" 38 | lines: 39 | description: | 40 | A `Squash::Symbolicator::Lines` object (as generated by 41 | `squash_ios_symbolicator`), YAML-serialized, then gzipped, then base 42 | 64-encoded. 43 | required: false 44 | type: string 45 | example: "eJxj4ci3kgiuzE3Kz8lMTizJL7Ky8snMSy1ms+J2yAExohkAxuwLNg==\n" 46 | -------------------------------------------------------------------------------- /lib/api/errors.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | module API 16 | # Raised when invalid attributes are provided to the worker. 17 | class InvalidAttributesError < StandardError; end 18 | 19 | # Raised when an unknown API key is provided. 20 | class UnknownAPIKeyError < StandardError; end 21 | end 22 | -------------------------------------------------------------------------------- /lib/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SquareSquash/web/e73f2805f9eb30780a5c213b001f0f4255660fbf/lib/assets/.gitkeep -------------------------------------------------------------------------------- /lib/assets/javascripts/accordion.js.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Square Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | root = exports ? this 16 | 17 | # Implements accordion behavior. An accordion container must have the class of 18 | # "accordion" and consist of one or more elements of class "accordion-pair". 19 | # Each of these elements must have an `