Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task: Release Candidate v2.0.2 #153

Merged
merged 36 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b4e192a
Fixed undefined var or method in ReportManagerApi
bogdanadrianmarc Dec 11, 2024
3db7ac3
Bumped app version
bogdanadrianmarc Dec 11, 2024
6df653c
Added changelog entry
bogdanadrianmarc Dec 11, 2024
f7bb53c
Merge pull request #151 from epimorphics/spike/internal-app-error-fix
bogdanadrianmarc Dec 11, 2024
d887de8
fix: remove error instrumentation from standard error handling
jonrandahl Dec 16, 2024
93545f7
fix: only trigger instrumentation on internal errors
jonrandahl Dec 16, 2024
94542b4
fix: improve error metrics reporting
jonrandahl Dec 16, 2024
2ae9978
fix: removes test environment from sentry
jonrandahl Dec 16, 2024
4eccd15
style: Return `false` instead of `nil` in predicate methods
jonrandahl Dec 18, 2024
c645381
fix: add fallbacks to current date if spec not available
jonrandahl Dec 18, 2024
eaf6775
style: disabled rubocop warnings
jonrandahl Dec 18, 2024
ab26367
fix: check for response first
jonrandahl Dec 18, 2024
e24515c
fix: updated message and removed underscore from variable that's used
jonrandahl Dec 18, 2024
0a79e0e
fix: ensure correct instrumentation for error
jonrandahl Dec 18, 2024
10ddf7f
fix: Replace specific fields when available
jonrandahl Dec 18, 2024
06f1ab5
fix: utilise safeNavigation to remove `NoMethodError for nil` errors
jonrandahl Dec 18, 2024
f764856
fix: don't throw unless it will be caught!
jonrandahl Dec 18, 2024
a58562f
style: disabled rubocop Metrics/MethodLength warning
jonrandahl Dec 18, 2024
b75fb80
fix: resolve missing error templates
jonrandahl Dec 18, 2024
c73ac29
build: updated Makefile to mirror use across company
jonrandahl Dec 18, 2024
b488414
docs: updated CHANGELOG
jonrandahl Dec 18, 2024
444885c
build: updated patch version cadence
jonrandahl Dec 18, 2024
64b41e2
fix: improved error handling on api response
jonrandahl Dec 18, 2024
bf33345
style: improved log message and additional rubocop linting fixes
jonrandahl Dec 18, 2024
353d32e
style: rubocop linting autofixes
jonrandahl Dec 18, 2024
9c1e473
fix: Prefer keyword arguments for arguments with a boolean default value
jonrandahl Dec 18, 2024
7d493db
fix: resolve `Metrics/CollectionLiteralLength` for long list of distr…
jonrandahl Dec 18, 2024
934468d
fix: Use `tag.div` instead of `tag(:div)`. (convention:Rails/ContentTag)
jonrandahl Dec 18, 2024
acff131
fix: sets Time.now to Time.current to ensure zone is in calculations
jonrandahl Dec 18, 2024
392e0dc
style: disabling rubocop linting warnings
jonrandahl Dec 18, 2024
553dc0a
style: rubocop auto removing of unnecessary disabling of rules
jonrandahl Dec 18, 2024
4f86b3d
style: disable rubocop `Style/ArgumentsForwarding`
jonrandahl Dec 18, 2024
da32d30
style: disable rubocop `Metrics/MethodLength` warning
jonrandahl Dec 18, 2024
20b67c9
Merge pull request #152 from epimorphics/spike/improve-metrics-logging
bogdanadrianmarc Dec 19, 2024
efa820d
Update step_select_dates.rb
jonrandahl Dec 20, 2024
ea0ec82
Merge branch 'dev' into task/rc-2.0.1
jonrandahl Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Standard Reports UI: change log

## 2.0.2 - 2024-12

- (Jon) Myriad of tweaks to ensure variables either fail quietly via safe
navigation or are set to a default value to prevent errors in the application
- (Jon) Updated the error template path to use `Rails.public_path` as well as
contain the `html` extension to ensure the correct template is rendered
- (Jon) Improves error metrics reporting to ensure that logging always happens
with the appropriate severity depending on the exception status while reducing
the types of errors that can trigger a an error metric and therefore a
notification in slack
[GH-149](https://github.com/epimorphics/hmlr-linked-data/issues/149)

## 2.0.1 - 2024-12

- (Bogdan) Fixed a bug that was causing an internal application error in
`ReportManagerApi`

## 2.0.0 - 2024-12

- (Bogdan) Updated all gems by regenerating `Gemfile.lock`
Expand All @@ -9,7 +26,8 @@

## 1.6.0 - 2024-10

- (Dan) Updates ruby version to 2.7.8 and alpine version to 3.16 [GH-143](https://github.com/epimorphics/standard-reports-ui/issues/143)
- (Dan) Updates ruby version to 2.7.8 and alpine version to 3.16
[GH-143](https://github.com/epimorphics/standard-reports-ui/issues/143)

## 1.5.4 - 2024-10

Expand Down
11 changes: 3 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ ${GITHUB_TOKEN}:
all: image

assets: auth
@./bin/bundle config set --local without 'development test'
@echo "Installing all packages ..."
@./bin/bundle install
@echo "Cleaning up precompiled assets ..."
@./bin/rails assets:clean assets:precompile

auth: ${GITHUB_TOKEN} ${BUNDLE_CFG}
Expand Down Expand Up @@ -68,12 +69,6 @@ image: auth
lint: assets
@./bin/bundle exec rubocop

local:
@echo "Installing all packages ..."
@./bin/bundle install
@echo "Starting local server ..."
@./bin/rails server -p ${PORT}

publish: image
@echo Publishing image: ${REPO}:${TAG} ...
@docker push ${REPO}:${TAG} 2>&1
Expand All @@ -86,7 +81,7 @@ run: start
@if docker network inspect dnet > /dev/null 2>&1; then echo "Using docker network dnet"; else echo "Create docker network dnet"; docker network create dnet; sleep 2; fi
@docker run -p ${PORT}:3000 -e API_SERVICE_URL=${API_SERVICE_URL} --network dnet --rm --name ${SHORTNAME} ${REPO}:${TAG}

server: assets start
server:
@export SECRET_KEY_BASE=$(./bin/rails secret)
@API_SERVICE_URL=${API_SERVICE_URL} ./bin/rails server -p ${PORT}

Expand Down
30 changes: 25 additions & 5 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ def log_request_result
# or attempt to render a generic error page if no specific error page exists
unless Rails.application.config.consider_all_requests_local
rescue_from StandardError do |e|
# Instrument ActiveSupport::Notifications for internal errors but only for non-404 errors:
unless e.is_a?(ActionController::RoutingError) || e.is_a?(ActionView::MissingTemplate)
ActiveSupport::Notifications.instrument('internal_error.application', exception: e)
end
# Trigger the appropriate error handling method based on the exception
case e.class
when ActionController::RoutingError, ActionView::MissingTemplate
Expand All @@ -51,6 +47,8 @@ def handle_internal_error(exception)
render_error(400)
else
Rails.logger.warn "No explicit error page for exception #{exception} - #{exception.class}"
# Instrument ActiveSupport::Notifications for internal server errors only:
instrument_internal_error(exception)
render_error(500)
end
end
Expand Down Expand Up @@ -83,7 +81,7 @@ def render_error(status)

def render_html_error_page(status)
render(layout: true,
file: Rails.root.join('public', 'landing', status.to_s),
file: Rails.public_path + "landing/#{status}.html",
status: status)
end

Expand Down Expand Up @@ -120,4 +118,26 @@ def detailed_request_log(duration)
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

# Notify subscriber(s) of an internal error event with the payload of the
# exception once done
# @param [exc] exp the exception that caused the error
# @return [ActiveSupport::Notifications::Event] provides an object-oriented
# interface to the event
def instrument_internal_error(exc) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
err = {
message: exc&.message || exc,
status: exc&.status || Rack::Utils::SYMBOL_TO_STATUS_CODE[exc]
}
err[:type] = exc.class&.name if exc&.class
err[:cause] = exc&.cause if exc&.cause
err[:backtrace] = exc&.backtrace if exc&.backtrace && Rails.env.development?
# Log the exception to the Rails logger with the appropriate severity
Rails.logger.send(err[:status] < 500 ? :warn : :error, JSON.generate(err))
# Return unless the status code is 500 or greater to ensure subscribers are NOT notified
return unless err[:status] >= 500

# Instrument the internal error event to notify subscribers of the error
ActiveSupport::Notifications.instrument('internal_error.application', exception: err)
end
end
2 changes: 1 addition & 1 deletion app/helpers/download_request_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def render_report_request(request)
end
end

def request_status(request)
def request_status(request) # rubocop:disable Metrics/MethodLength
capture do
if request.unknown?
concat render_unknown_request(request)
Expand Down
8 changes: 4 additions & 4 deletions app/helpers/report_design_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def layout_values_as_toggle_buttons(step, values, radio, cls = '')
end
end

def toggle_button_option(step, value, radio, single_value)
def toggle_button_option(step, value, radio, single_value) # rubocop:disable Metrics/MethodLength
active = value.active? || single_value

content_tag(:div, class: 'o-form-control') do
Expand Down Expand Up @@ -116,7 +116,7 @@ def selected_area_summary(workflow)
end

def layout_custom_dates(delta, step, workflow)
year = Time.now.year - delta
year = Time.current.year - delta
content_tag(:div, class: 'row') do
concat(content_tag(:div, class: 'col-sm-12 col-md-1') do
content_tag(:h3, year.to_s, class: 'u-font-bold u-align-top')
Expand All @@ -130,7 +130,7 @@ def layout_custom_dates(delta, step, workflow)
end

def layout_all_year(step, year, workflow)
all_year = year == Time.now.year ? 'to date' : 'all year'
all_year = year == Time.current.year ? 'to date' : 'all year'
checked = workflow.has_state?(step.param_name, year.to_s)
capture do
concat prompted_row(
Expand Down Expand Up @@ -218,7 +218,7 @@ def show_change_link(workflow, step)

def layout_map_control(_step)
content_tag(:div, class: 'col-sm-12 col-md-6') do
tag(:div, id: 'map', class: 'o-map')
tag.div(id: 'map', class: 'o-map')
end
end
end
4 changes: 2 additions & 2 deletions app/lib/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Version
MAJOR = 2
MINOR = 0
PATCH = 0
PATCH = 2
SUFFIX = nil
VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}#{SUFFIX && ".#{SUFFIX}"}"
VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}#{SUFFIX && ".#{SUFFIX}"}".freeze
end
2 changes: 1 addition & 1 deletion app/models/report_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def normalize_period(report_manager)
end
end

def latest_quarter(report_manager)
def latest_quarter(report_manager) # rubocop:disable Metrics/MethodLength
case report_manager.latest_month
when 1..2
"#{report_manager.latest_year - 1}-Q4"
Expand Down
2 changes: 1 addition & 1 deletion app/models/step_select_aggregation_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize
super(:select_aggregation_type, :aggregate, :radio)
end

def values_options(workflow) # rubocop:disable Metrics/CyclomaticComplexity
def values_options(workflow) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
case workflow.state(:areaType)
when 'country'
[AGGREGATE_BY_REGION, AGGREGATE_BY_COUNTY, AGGREGATE_BY_DISTRICT,
Expand Down
6 changes: 3 additions & 3 deletions app/models/step_select_dates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ def generic_name
'select dates'
end

def each_year(hidden_only = true, &block)
def each_year(hidden_only = true, &block) # rubocop:disable Style/OptionalBooleanParameter
start_delta = hidden_only ? YEARS_SHOWN_BY_DEFAULT : 0
delta = Time.now.year - EARLIEST_YEAR
delta = Time.current.year - EARLIEST_YEAR
(start_delta..delta).each(&block)
end

Expand Down Expand Up @@ -95,7 +95,7 @@ def latest_values(workflow)
]
end

def summarise_value
def summarise_value # rubocop:disable Metrics/MethodLength
proc { |state_value|
s = case state_value.to_sym
when :ytd
Expand Down
3 changes: 2 additions & 1 deletion app/models/step_select_district.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ def successor_step
:select_aggregation_type
end

NAMES = [
# The names of all the districts
NAMES = [ # rubocop:disable Metrics/CollectionLiteralLength
'ADUR',
'ALLERDALE',
'AMBER VALLEY',
Expand Down
2 changes: 1 addition & 1 deletion app/models/step_select_postcode_area.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Workflow step of selecting a postcode area
class StepSelectPostcodeArea < StepSelectPostcode
VALIDATION = /\A[A-Z][A-Z]?\Z/.freeze
VALIDATION = /\A[A-Z][A-Z]?\Z/

def initialize
super(:select_pc_area)
Expand Down
2 changes: 1 addition & 1 deletion app/models/step_select_postcode_district.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Workflow step of selecting a postcode district
class StepSelectPostcodeDistrict < StepSelectPostcode
VALIDATION = /\A[A-Z][A-Z]?[0-9][0-9]?[A-Z]?\Z/.freeze
VALIDATION = /\A[A-Z][A-Z]?[0-9][0-9]?[A-Z]?\Z/

def initialize
super(:select_pc_district)
Expand Down
2 changes: 1 addition & 1 deletion app/models/step_select_postcode_sector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Workflow step of selecting a postcode sector
class StepSelectPostcodeSector < StepSelectPostcode
VALIDATION = /\A[A-Z][A-Z]?[0-9][0-9]?[A-Z]? [0-9]\Z/.freeze
VALIDATION = /\A[A-Z][A-Z]?[0-9][0-9]?[A-Z]? [0-9]\Z/

def initialize
super(:select_pc_sector)
Expand Down
2 changes: 1 addition & 1 deletion app/models/workflow.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

# Model encapsulating the report-generation workflow
class Workflow
class Workflow # rubocop:disable Metrics/ClassLength
extend Forwardable

attr_reader :step_history
Expand Down
33 changes: 23 additions & 10 deletions app/services/report_manager.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

# Service object for interacting with remote service-manager API
class ReportManager
class ReportManager # rubocop:disable Metrics/ClassLength
def initialize(config = nil)
return unless config

Expand All @@ -17,15 +17,24 @@ def initialize(config = nil)
end

def latest_month
latest_month_spec.split('-').second.to_i
latest_month_spec && latest_month_spec.split('-').second.to_i
rescue StandardError => e
msg = "Failed to retreive latest month from #{url}latest-month-available"
Rails.logger.error { "#{msg}: #{e}" }
end

def latest_year
latest_month_spec.split('-').first.to_i
latest_month_spec && latest_month_spec.split('-').first.to_i
rescue StandardError => e
msg = "Failed to retreive latest year from #{url}latest-month-available"
Rails.logger.error { "#{msg}: #{e}" }
end

def latest_quarter
(latest_month / 3).to_i
latest_month && (latest_month / 3).to_i
rescue StandardError => e
msg = "Failed to retreive latest quarter from #{url}latest-month-available"
Rails.logger.error { "#{msg}: #{e}" }
end

def latest_month_spec
Expand Down Expand Up @@ -74,7 +83,7 @@ def start_requests(params)
# a=1&b[]=2&b[]=3
# becomes
# [{a: 1, b: 2}, {a: 1, b: 3}]
def create_params_sets(params)
def create_params_sets(params) # rubocop:disable Metrics/MethodLength
product = [{}]

params.each do |k, v|
Expand All @@ -95,7 +104,7 @@ def create_params_sets(params)

def start_request(req_spec)
json = api.post_json("#{url}report-request", req_spec.to_hash)
Rails.logger.debug { "ReportManager: #{json}" } if Rails.env.development?
Rails.logger.debug { "ReportManager response: #{json}" } if Rails.env.development?
ReportStatus.new(json)
end

Expand All @@ -113,15 +122,19 @@ def validate?(params)
end

def key_present?(params, key)
return unless !params.key?(key) || params[key].nil? || params[key].to_s.empty?
return false unless !params.key?(key) ||
params[key].nil? ||
params[key].to_s.empty?

@errors ||= []
@errors << "missing parameter #{key}"
end

def array_key_present?(params, key)
return unless !params.key?(key) || params[key].nil? ||
!params[key].is_a?(Array) || params[key].empty?
return false unless !params.key?(key) ||
params[key].nil? ||
!params[key].is_a?(Array) ||
params[key].empty?

@errors ||= []
@errors << "missing parameter #{key}"
Expand All @@ -131,7 +144,7 @@ def valid_postcodes?(params)
area = params[:area]
pattern = validation_pattern(params)

return unless pattern && !pattern.match?(area)
return false unless pattern && !pattern.match?(area)

@errors ||= []
@errors << 'invalid postal code'
Expand Down
Loading