diff --git a/.gitignore b/.gitignore index ecdca58..d3ecc88 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ build-iPhoneSimulator/ .rvmrc vendor/ *.html +.cache/ diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..6c1a90c --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,14 @@ +--- +Style/ClassAndModuleChildren: + Enabled: false +Style/HashSyntax: + EnforcedStyle: 'hash_rockets' +Style/RedundantReturn: + Enabled: false +Style/TrailingCommaInLiteral: + EnforcedStyleForMultiline: 'consistent_comma' +Metrics/MethodLength: + Enabled: false +Metrics/BlockLength: + Exclude: + - 'spec/**/*.rb' diff --git a/Dockerfile b/Dockerfile index e41e227..5243c94 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ ADD views ${APP_DIR}/views/ ADD assets ${APP_DIR}/assets/ RUN apk add -U ${BUILD_PKGS} && \ - bundle install && \ + bundle install --without test && \ apk del ${BUILD_PKGS} && \ rm -rf /var/cache/apk/* diff --git a/Gemfile b/Gemfile index 7ea261f..c21a196 100644 --- a/Gemfile +++ b/Gemfile @@ -6,10 +6,11 @@ gem 'faraday_middleware' gem 'haml' gem 'mini_cache' gem 'puma' -gem 'sentry-raven' gem 'sentry-api' +gem 'sentry-raven' gem 'sinatra' group :test do gem 'rspec' + gem 'rubocop' end diff --git a/Gemfile.lock b/Gemfile.lock index 688d5e7..ad3acf7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,7 @@ GEM remote: https://rubygems.org/ specs: + ast (2.3.0) concurrent-ruby (1.0.5) diff-lcs (1.3) faraday (0.13.1) @@ -21,10 +22,17 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) mustermann (1.0.1) + parallel (1.12.0) + parser (2.4.0.0) + ast (~> 2.2) + powerpack (0.1.1) puma (3.10.0) rack (2.0.3) rack-protection (2.0.0) rack + rainbow (2.2.2) + rake + rake (12.0.0) rspec (3.6.0) rspec-core (~> 3.6.0) rspec-expectations (~> 3.6.0) @@ -38,6 +46,14 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.6.0) rspec-support (3.6.0) + rubocop (0.49.1) + parallel (~> 1.10) + parser (>= 2.3.3.1, < 3.0) + powerpack (~> 0.1) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 1.0, >= 1.0.1) + ruby-progressbar (1.8.1) sentry-api (0.3.3) httmultiparty (~> 0.3.16) sentry-raven (2.6.3) @@ -49,6 +65,7 @@ GEM tilt (~> 2.0) temple (0.8.0) tilt (2.0.8) + unicode-display_width (1.3.0) PLATFORMS ruby @@ -61,6 +78,7 @@ DEPENDENCIES mini_cache puma rspec + rubocop sentry-api sentry-raven sinatra diff --git a/Makefile b/Makefile index 01390cb..349f7f6 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,9 @@ spec: depends --format progress \ --format html --out rspec.html +rubocop: depends + ./scripts/ruby bundle exec rubocop + depends: Gemfile ./scripts/ruby bundle install @@ -24,4 +27,4 @@ container: depends Dockerfile clean: rm -rf vendor -.PHONY: all depends clean run check container spec check-container +.PHONY: all depends clean run check container spec check-container rubocop diff --git a/app/canary.rb b/app/canary.rb index b183a7a..8ca7959 100644 --- a/app/canary.rb +++ b/app/canary.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'haml' require 'raven' require 'sinatra/base' @@ -10,6 +8,7 @@ require 'canary/dao/sentry' module CodeValet module Canary + # Basic Canary web app entry point. class App < Sinatra::Base enable :sessions enable :raise_errors @@ -25,33 +24,24 @@ module CodeValet end get '/' do - projects = [] - begin - projects = SentryApi.projects - rescue StandardError => exc - Raven.capture_exception(exc) - end - haml :index, - :layout => :_base, - :locals => { - :sentry => DAO::Sentry.new, - :jenkins => DAO::Jenkins.new, - } + :layout => :_base, + :locals => { + :sentry => DAO::Sentry.new, + :jenkins => DAO::Jenkins.new, + } end get '/issue/:id' do - issue = nil - events = [] - issue_id = params['id'] sentry = DAO::Sentry.new + issue_id = params['id'] haml :issue, - :layout => :_base, - :locals => { - :issue => sentry.issue_by(issue_id), - :events => sentry.events_for_issue(issue_id), - } + :layout => :_base, + :locals => { + :issue => sentry.issue_by(issue_id), + :events => sentry.events_for_issue(issue_id), + } end end end diff --git a/app/canary/dao.rb b/app/canary/dao.rb index e77ef6b..07b9087 100644 --- a/app/canary/dao.rb +++ b/app/canary/dao.rb @@ -7,8 +7,15 @@ module CodeValet # The DAO module contains some data-access objects which are to be used # from the web tier. module DAO - NET_ERRORS = [Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, - Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError] + NET_ERRORS = [ + Timeout::Error, + Errno::EINVAL, + Errno::ECONNRESET, + EOFError, + Net::HTTPBadResponse, + Net::HTTPHeaderSyntaxError, + Net::ProtocolError, + ].freeze # Access the caching object # diff --git a/app/canary/dao/jenkins.rb b/app/canary/dao/jenkins.rb index 980bb30..934a9e8 100644 --- a/app/canary/dao/jenkins.rb +++ b/app/canary/dao/jenkins.rb @@ -3,8 +3,11 @@ require 'canary/dao' require 'raven' module CodeValet::Canary::DAO + # This DAO provides some basic caching calls through to Jenkins instances in + # the Code Valet environment. The data it accesses is not "API" data per se + # but rather information about the state of the instance. class Jenkins - # Base URL to contrict + # Base URL to contrict URL_BASE = ENV['JENKINS_URL_BASE'] || 'https://codevalet.io' CACHE_SECONDS = 300 @@ -14,15 +17,15 @@ module CodeValet::Canary::DAO return !@error.nil? end - def rebuiltAlpha + def rebuilt_alpha return cache.get_or_set('rebuiltAlpha', :expires_in => CACHE_SECONDS) do - rebuiltFor('codevalet') + rebuilt_for('codevalet') end end - def rebuiltGA + def rebuilt_ga return cache.get_or_set('rebuiltGA', :expires_in => CACHE_SECONDS) do - rebuiltFor('rtyler') + rebuilt_for('rtyler') end end @@ -31,14 +34,13 @@ module CodeValet::Canary::DAO # # @return [String] response from the server if we reached it # @return [nil] nil on no response, #errored? should be set - def rebuiltFor(user) + def rebuilt_for(user) # NOTE: worth investigating whether Jenkins will provide the appropriate - # caching headers to + # caching headers to url = "#{URL_BASE}/u/#{user}/userContent/builtOn.txt" response = connection.get(url) - if response.success? - return response.body - end + return response.body if response.success? + @error = response.status return nil rescue *CodeValet::Canary::DAO::NET_ERRORS => e @@ -53,14 +55,13 @@ module CodeValet::Canary::DAO private def connection - return Faraday.new(:ssl => {:verify => true}) do |f| + return Faraday.new(:ssl => { :verify => true }) do |f| f.adapter Faraday.default_adapter f.options.timeout = 4 f.options.open_timeout = 3 end end - def cache return CodeValet::Canary::DAO.cache end diff --git a/app/canary/dao/sentry.rb b/app/canary/dao/sentry.rb index a74d985..6eb52f5 100644 --- a/app/canary/dao/sentry.rb +++ b/app/canary/dao/sentry.rb @@ -5,6 +5,10 @@ require 'raven' require 'sentry-api' module CodeValet::Canary::DAO + # The Sentry DAO provides some caching calls through to the SentryApi gem + # + # In the future it's highly likely that this class sprouts some direct + # Sentry REST API calls class Sentry attr_reader :error @@ -25,8 +29,8 @@ module CodeValet::Canary::DAO # added/changed very often return cache.get_or_set('SentryApi#projects', :expires_in => 10 * CACHE_SECONDS) do - SentryApi.projects - end + SentryApi.projects + end rescue *CodeValet::Canary::DAO::NET_ERRORS, SentryApi::Error::Parsing => e @error = e return [] @@ -44,8 +48,8 @@ module CodeValet::Canary::DAO def issues_for(project_key) return cache.get_or_set("SentryApi#project_issues(#{project_key})", :expires_in => CACHE_SECONDS) do - SentryApi.project_issues(project_key) - end + SentryApi.project_issues(project_key) + end rescue *CodeValet::Canary::DAO::NET_ERRORS, SentryApi::Error::Parsing => e @error = e return [] @@ -55,7 +59,6 @@ module CodeValet::Canary::DAO return [] end - # Return the issue by the given Sentry issue ID # # This response will be cached @@ -65,8 +68,8 @@ module CodeValet::Canary::DAO def issue_by(id) return cache.get_or_set("SentryApi#issue(#{id})", :expires_in => 5 * CACHE_SECONDS) do - SentryApi.issue(id) - end + SentryApi.issue(id) + end rescue *CodeValet::Canary::DAO::NET_ERRORS, SentryApi::Error::Parsing => e @error = e return nil @@ -79,8 +82,8 @@ module CodeValet::Canary::DAO def events_for_issue(id) return cache.get_or_set("SentryApi#issue_events(#{id})", :expires_in => CACHE_SECONDS) do - SentryApi.issue_events(id) - end + SentryApi.issue_events(id) + end rescue *CodeValet::Canary::DAO::NET_ERRORS, SentryApi::Error::Parsing => e @error = e return nil diff --git a/config.ru b/config.ru index a02715b..e0ae260 100644 --- a/config.ru +++ b/config.ru @@ -6,7 +6,7 @@ ENV['RACK_ENV'] ||= 'development' require 'canary' require 'raven' -use Rack::Static, :urls => ["/css", "/img", "/js"], :root => "public" +use Rack::Static, :urls => ['/css', '/img', '/js'], :root => 'public' use Raven::Rack run CodeValet::Canary::App diff --git a/scripts/ruby b/scripts/ruby index a2b48be..f504e65 100755 --- a/scripts/ruby +++ b/scripts/ruby @@ -11,6 +11,7 @@ exec docker run --rm ${TTY_ARGS} \ -u $(id -u):$(id -g) \ -w ${PWD} \ -v ${PWD}:${PWD} \ + -e HOME=$PWD \ -e LANG=C.UTF-8 \ -e GEM_HOME=${PWD}/vendor/gems \ -e BUNDLE_PATH=${PWD}/vendor/gems \ diff --git a/spec/dao/jenkins_spec.rb b/spec/dao/jenkins_spec.rb index 25aad7a..c0edf01 100644 --- a/spec/dao/jenkins_spec.rb +++ b/spec/dao/jenkins_spec.rb @@ -14,26 +14,26 @@ describe CodeValet::Canary::DAO::Jenkins do context 'with a stubbed network call' do let(:response) { 'stubbed!' } before :each do - expect(subject).to receive(:rebuiltFor).and_return(response) + expect(subject).to receive(:rebuilt_for).and_return(response) end - it 'provides a response on #rebuiltAlpha' do - expect(subject.rebuiltAlpha).to eql(response) + it 'provides a response on #rebuilt_alpha' do + expect(subject.rebuilt_alpha).to eql(response) end - it 'provides a response on #rebuiltGA' do - expect(subject.rebuiltGA).to eql(response) + it 'provides a response on #rebuilt_ga' do + expect(subject.rebuilt_ga).to eql(response) end - it 'should cache subsequent calls on #rebuiltAlpha' do + it 'should cache subsequent calls on #rebuilt_alpha' do 3.times do - expect(subject.rebuiltAlpha).to eql(response) + expect(subject.rebuilt_alpha).to eql(response) end end - it 'should cache subsequent calls on #rebuiltGA' do + it 'should cache subsequent calls on #rebuilt_ga' do 3.times do - expect(subject.rebuiltGA).to eql(response) + expect(subject.rebuilt_ga).to eql(response) end end end @@ -43,7 +43,7 @@ describe CodeValet::Canary::DAO::Jenkins do it 'should silently handle ECONNRESET' do expect(subject).to receive(:connection).and_raise(Errno::ECONNRESET) - expect(subject.rebuiltGA).to be_nil + expect(subject.rebuilt_ga).to be_nil expect(subject).to be_errored end end @@ -53,7 +53,7 @@ describe CodeValet::Canary::DAO::Jenkins do expect(subject).to receive(:connection).and_raise(JSON::ParserError) expect(Raven).to receive(:capture_exception) - expect(subject.rebuiltGA).to be_nil + expect(subject.rebuilt_ga).to be_nil expect(subject).to be_errored end end diff --git a/spec/dao/sentry_spec.rb b/spec/dao/sentry_spec.rb index b66cf95..038367b 100644 --- a/spec/dao/sentry_spec.rb +++ b/spec/dao/sentry_spec.rb @@ -66,7 +66,8 @@ describe CodeValet::Canary::DAO::Sentry do # https://github.com/CodeValet/canary/issues/5 it 'should gracefully handle Sentry API parsing errors' do - expect(SentryApi).to receive(:project_issues).and_raise(SentryApi::Error::Parsing) + expect(SentryApi).to \ + receive(:project_issues).and_raise(SentryApi::Error::Parsing) expect(Raven).not_to receive(:capture_exception) expect(issues).to be_empty @@ -93,7 +94,7 @@ describe CodeValet::Canary::DAO::Sentry do describe '#issue_by' do let(:dao) { described_class.new } subject(:issue) { dao.issue_by('fake-id') } - let(:response) { Hash.new } + let(:response) { {} } it 'should return SentryApi#issue' do expect(SentryApi).to receive(:issue).and_return(response) @@ -126,7 +127,7 @@ describe CodeValet::Canary::DAO::Sentry do describe '#events_for_issue' do let(:dao) { described_class.new } subject(:issue) { dao.events_for_issue('fake-id') } - let(:response) { Hash.new } + let(:response) { {} } it 'should return SentryApi#issue' do expect(SentryApi).to receive(:issue_events).and_return(response) diff --git a/views/index.haml b/views/index.haml index afedc8c..e9cf5e7 100644 --- a/views/index.haml +++ b/views/index.haml @@ -24,14 +24,14 @@ alpha channel was last rebuilt on: %code - = jenkins.rebuiltAlpha + = jenkins.rebuilt_alpha %p The %strong general availability channel was last rebuilt on: %code - = jenkins.rebuiltGA + = jenkins.rebuilt_ga .row .col-md-12