diff --git a/lib/sonarqube/client.rb b/lib/sonarqube/client.rb index 9a27857..bfa7db9 100644 --- a/lib/sonarqube/client.rb +++ b/lib/sonarqube/client.rb @@ -9,6 +9,7 @@ module Sonarqube include Groups include Permissions include Projects + include QualityGates include Tokens include Users diff --git a/lib/sonarqube/client/quality_gates.rb b/lib/sonarqube/client/quality_gates.rb new file mode 100644 index 0000000..bbdfbbe --- /dev/null +++ b/lib/sonarqube/client/quality_gates.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +class Sonarqube::Client + # Defines methods related to tokens. + # @see https://SONAR_URL/web_api/api/qualitygates + module QualityGates + ALLOWED_OPERATORS = %w(LT GT) + ALLOWED_METRICS = %w( + coverage new_coverage duplicated_lines_density + new_duplicated_lines_density reliability_rating new_reliability_rating + maintainability_rating new_maintainability_rating + ) + # Create new quality gate. + # + # @example + # Sonarqube.create_quality_gate('name_quality_gate') + # + # # Gracefully continue if gate already exists + # begin + # Sonarqube.create_quality_gate('name_quality_gate') + # rescue Sonarqube::Error::BadRequest => error + # raise unless error.message =~ /Name has already been taken/ + # end + # + # @param [String] name (required) Quality Gate name. + # @return [Sonarqube::ObjectifiedHash] + def create_quality_gate(name) + raise ArgumentError, 'Missing required parameters' if name.nil? + + body = { name: name } + post('/api/qualitygates/create', body: body) + end + alias quality_gate_create create_quality_gate + + # Create condition for a quality gate. + # + # @example + # # Create a condition that errors when coverage is below 90% + # Sonarqube.create_quality_gate_condition('name_quality_gate', 'coverage', '90') + # + # # Create a condition that errors when code duplication is > 3% + # Sonarqube.create_quality_gate_condition('name_quality_gate', 'duplicated_lines_density', + # '3', 'GT') + # + # @param [String] name (required) Quality Gate name. + # @param [String] metric (required) SonarQube metric name. + # @param [String] error_threshold (required) Error threshold value + # @param [String] operator (required) Operator - LT for <; GT for > + # @return [Sonarqube::ObjectifiedHash] + def create_quality_gate_condition(name, metric, error_threshold, operator = 'LT') + raise ArgumentError, 'Missing required parameters' if name.nil? || metric.nil? || error_threshold.nil? + raise ArgumentError, "Operator must be in #{ALLOWED_OPERATORS.join(', ')}" unless ALLOWED_OPERATORS.include?(operator) + raise ArgumentError, "Metric must be in #{ALLOWED_METRICS.join(', ')}" unless ALLOWED_METRICS.include?(metric) + + body = { + gateName: name, + metric: metric, + error: error_threshold, + op: operator + } + post('/api/qualitygates/create_condition', body: body) + end + alias quality_gate_condition_create create_quality_gate_condition + + # Set the default quality gate. + # + # @example + # Sonarqube.set_default_quality_gate('name_quality_gate') + # + # @param [String] name (required) Quality Gate name. + # @return [Sonarqube::ObjectifiedHash] + def set_default_quality_gate(name) + raise ArgumentError, 'Missing required parameters' if name.nil? + + body = { name: name } + post('/api/qualitygates/set_as_default', body: body) + end + alias default_quality_gate_set set_default_quality_gate + + # List quality gates. + # + # @example + # Sonarqube.list_quality_gates + # + # @return [Sonarqube::ObjectifiedHash]. + def list_quality_gates + get('/api/qualitygates/list') + end + alias quality_gates_list list_quality_gates + end +end diff --git a/spec/fixtures/quality_gates_condition_create.json b/spec/fixtures/quality_gates_condition_create.json new file mode 100644 index 0000000..3682110 --- /dev/null +++ b/spec/fixtures/quality_gates_condition_create.json @@ -0,0 +1,6 @@ +{ + "id": "AU-Tpxb--iU5OvuD2FLy", + "metric": "coverage", + "op": "LT", + "error": "90" +} diff --git a/spec/fixtures/quality_gates_create.json b/spec/fixtures/quality_gates_create.json new file mode 100644 index 0000000..260892c --- /dev/null +++ b/spec/fixtures/quality_gates_create.json @@ -0,0 +1,4 @@ +{ + "id": "AU-Tpxb--iU5OvuD2FLy", + "name": "name_quality_gate" +} diff --git a/spec/fixtures/quality_gates_list.json b/spec/fixtures/quality_gates_list.json new file mode 100644 index 0000000..cd36b8c --- /dev/null +++ b/spec/fixtures/quality_gates_list.json @@ -0,0 +1,38 @@ +{ + "qualitygates": [ + { + "id": "AU-Tpxb--iU5OvuD2FLy", + "name": "Sonar way", + "isDefault": true, + "isBuiltIn": true, + "actions": { + "rename": false, + "setAsDefault": false, + "copy": true, + "associateProjects": false, + "delete": false, + "manageConditions": false, + "delegate": false + } + }, + { + "id": "AU-Tpxb--iU5OvuD2FLz", + "name": "Sonar way - Without Coverage", + "isDefault": false, + "isBuiltIn": false, + "actions": { + "rename": true, + "setAsDefault": true, + "copy": true, + "associateProjects": true, + "delete": true, + "manageConditions": true, + "delegate": true + } + } + ], + "default": 8, + "actions": { + "create": true + } +} diff --git a/spec/fixtures/quality_gates_set_default.json b/spec/fixtures/quality_gates_set_default.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/spec/fixtures/quality_gates_set_default.json @@ -0,0 +1 @@ +{} diff --git a/spec/sonarqube/client/quality_gates_spec.rb b/spec/sonarqube/client/quality_gates_spec.rb new file mode 100644 index 0000000..c55ccd3 --- /dev/null +++ b/spec/sonarqube/client/quality_gates_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Sonarqube::Client do + describe '.quality_gate_create' do + before do + stub_post('/api/qualitygates/create', 'quality_gates_create') + @quality_gate = Sonarqube.create_quality_gate('name_quality_gate') + end + + it 'gets the correct resource' do + expect(a_post('/api/qualitygates/create')).to have_been_made + end + + it 'returns the quality gate ID' do + expect(@quality_gate).to be_a Sonarqube::ObjectifiedHash + expect(@quality_gate.id).to eq('AU-Tpxb--iU5OvuD2FLy') + end + end + + describe '.quality_gate_condition_create' do + before do + stub_post('/api/qualitygates/create_condition', 'quality_gates_condition_create') + @condition = Sonarqube.create_quality_gate_condition('name_quality_gate', + 'coverage', '90', + 'LT') + end + + it 'gets the correct resource' do + expect(a_post('/api/qualitygates/create_condition')).to have_been_made + end + + it 'returns the quality gate condition details' do + expect(@condition).to be_a Sonarqube::ObjectifiedHash + expect(@condition.metric).to eq('coverage') + end + end + + describe '.default_quality_gate_set' do + before do + stub_post('/api/qualitygates/set_as_default', 'quality_gates_set_default') + Sonarqube.set_default_quality_gate('name_quality_gate') + end + + it 'gets the correct resource' do + expect(a_post('/api/qualitygates/set_as_default')).to have_been_made + end + end + + describe '.quality_gates_list' do + before do + stub_get('/api/qualitygates/list', 'quality_gates_list') + @result = Sonarqube.list_quality_gates + end + + it 'returns array of quality gates' do + expect(@result.qualitygates).to be_a(Array) + end + + it 'provides details of each quality gate' do + expect(@result.qualitygates.first.name).to eq('Sonar way') + end + end +end