Commit be7106a1 authored by Leandro Camargo's avatar Leandro Camargo

Force coverage value to always be surrounded by '/'

parent f8bec0d1
......@@ -275,8 +275,10 @@ module Ci
end
def update_coverage
return unless project
return unless regex = self.coverage_regex
regex = coverage_regex.to_s[1...-1]
return if regex.blank?
coverage = extract_coverage(trace, regex)
if coverage.is_a? Numeric
......@@ -522,7 +524,9 @@ module Ci
end
def coverage_regex
super || project.build_coverage_regex
super ||
project.try(:build_coverage_regex).presence &&
"/#{project.try(:build_coverage_regex)}/"
end
def when
......
......@@ -286,9 +286,10 @@ build outputs. Setting this up globally will make all the jobs to use this
setting for output filtering and extracting the coverage information from your
builds.
Regular expressions are used by default. So using surrounding `/` is optional,
given it'll always be read as a regular expression. Don't forget to escape
special characters whenever you want to match them literally.
Regular expressions are the only valid kind of value expected here. So, using
surrounding `/` is mandatory in order to consistently and explicitly represent
a regular expression string. You must escape special characters if you want to
match them literally.
A simple example:
```yaml
......
......@@ -11,14 +11,6 @@ module Gitlab
validations do
validates :config, regexp: true
end
def value
if @config.first == '/' && @config.last == '/'
@config[1...-1]
else
@config
end
end
end
end
end
......
......@@ -9,15 +9,7 @@ module Gitlab
include Validatable
validations do
include LegacyValidationHelpers
validate :array_of_strings_or_regexps
def array_of_strings_or_regexps
unless validate_array_of_strings_or_regexps(config)
errors.add(:config, 'should be an array of strings or regexps')
end
end
validates :config, array_of_strings_or_regexps: true
end
end
end
......
......@@ -62,6 +62,45 @@ module Gitlab
record.errors.add(attribute, 'must be a regular expression')
end
end
private
def look_like_regexp?(value)
value =~ %r{\A/.*/\z}
end
def validate_regexp(value)
look_like_regexp?(value) &&
Regexp.new(value.to_s[1...-1]) &&
true
rescue RegexpError
false
end
end
class ArrayOfStringsOrRegexps < RegexpValidator
def validate_each(record, attribute, value)
unless validate_array_of_strings_or_regexps(value)
record.errors.add(attribute, 'should be an array of strings or regexps')
end
end
private
def validate_array_of_strings_or_regexps(values)
values.is_a?(Array) && values.all?(&method(:validate_string_or_regexp))
end
def validate_string_or_regexp(value)
return true if value.is_a?(Symbol)
return false unless value.is_a?(String)
if look_like_regexp?(value)
validate_regexp(value)
else
true
end
end
end
class TypeValidator < ActiveModel::EachValidator
......
......@@ -13,11 +13,11 @@ module Ci
context 'when config has coverage set at the global scope' do
before do
config_base.update(coverage: '\(\d+\.\d+\) covered')
config_base.update(coverage: '/\(\d+\.\d+\) covered/')
end
context "and 'rspec' job doesn't have coverage set" do
it { is_expected.to include(coverage_regex: '\(\d+\.\d+\) covered') }
it { is_expected.to include(coverage_regex: '/\(\d+\.\d+\) covered/') }
end
context "but 'rspec' job also has coverage set" do
......@@ -25,7 +25,7 @@ module Ci
config_base[:rspec][:coverage] = '/Code coverage: \d+\.\d+/'
end
it { is_expected.to include(coverage_regex: 'Code coverage: \d+\.\d+') }
it { is_expected.to include(coverage_regex: '/Code coverage: \d+\.\d+/') }
end
end
end
......
......@@ -4,31 +4,26 @@ describe Gitlab::Ci::Config::Entry::Coverage do
let(:entry) { described_class.new(config) }
describe 'validations' do
context "when entry config value is correct without surrounding '/'" do
context "when entry config value doesn't have the surrounding '/'" do
let(:config) { 'Code coverage: \d+\.\d+' }
describe '#value' do
subject { entry.value }
it { is_expected.to eq(config) }
end
describe '#errors' do
subject { entry.errors }
it { is_expected.to be_empty }
it { is_expected.to include(/coverage config must be a regular expression/) }
end
describe '#valid?' do
subject { entry }
it { is_expected.to be_valid }
it { is_expected.not_to be_valid }
end
end
context "when entry config value is correct with surrounding '/'" do
context "when entry config value has the surrounding '/'" do
let(:config) { '/Code coverage: \d+\.\d+/' }
describe '#value' do
subject { entry.value }
it { is_expected.to eq(config[1...-1]) }
it { is_expected.to eq(config) }
end
describe '#errors' do
......@@ -42,7 +37,7 @@ describe Gitlab::Ci::Config::Entry::Coverage do
end
end
context 'when entry value is not correct' do
context 'when entry value is not valid' do
let(:config) { '(malformed regexp' }
describe '#errors' do
......
......@@ -224,19 +224,20 @@ describe Ci::Build, :models do
describe '#coverage_regex' do
subject { build.coverage_regex }
context 'when project has build_coverage_regex set' do
let(:project_regex) { '\(\d+\.\d+\) covered' }
let(:build_regex) { 'Code coverage: \d+\.\d+' }
context 'when project has build_coverage_regex set' do
before do
project.build_coverage_regex = project_regex
end
context 'and coverage_regex attribute is not set' do
it { is_expected.to eq(project_regex) }
it { is_expected.to eq("/#{project_regex}/") }
end
context 'but coverage_regex attribute is also set' do
let(:build_regex) { '/Code coverage: \d+\.\d+/' }
before do
build.coverage_regex = build_regex
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment