diff --git a/app/finders/repositories/changelog_tag_finder.rb b/app/finders/repositories/changelog_tag_finder.rb index 7dd7404730f779245079f9e213bb248cbb22a3d3..d90ac6cc98fa39d7481f8320a297e04f3d471ed7 100644 --- a/app/finders/repositories/changelog_tag_finder.rb +++ b/app/finders/repositories/changelog_tag_finder.rb @@ -33,40 +33,16 @@ def initialize(project, regex: Gitlab::Changelog::Config::DEFAULT_TAG_REGEX) def execute(new_version) tags = {} - versions = [new_version] - - begin - regex = Gitlab::UntrustedRegexp.new(@regex) - rescue RegexpError => e - # The error messages produced by default are not very helpful, so we - # raise a better one here. We raise the specific error here so its - # message is displayed in the API (where we catch this specific - # error). - raise( - Gitlab::Changelog::Error, - "The regular expression to use for finding the previous tag for a version is invalid: #{e.message}" - ) - end - - @project.repository.tags.each do |tag| - matches = regex.match(tag.name) - - next unless matches - # When using this class for generating changelog data for a range of - # commits, we want to compare against the tag of the last _stable_ - # release; not some random RC that came after that. - next if matches[:pre] + requested_version = extract_version(new_version) + return unless requested_version - major = matches[:major] - minor = matches[:minor] - patch = matches[:patch] - build = matches[:meta] + versions = [requested_version] - next unless major && minor && patch + @project.repository.tags.each do |tag| + version = extract_version(tag.name) - version = "#{major}.#{minor}.#{patch}" - version += "+#{build}" if build + next unless version tags[version] = tag versions << version @@ -74,9 +50,47 @@ def execute(new_version) VersionSorter.sort!(versions) - index = versions.index(new_version) + index = versions.index(requested_version) tags[versions[index - 1]] if index&.positive? end + + private + + def version_matcher + @version_matcher ||= Gitlab::UntrustedRegexp.new(@regex) + rescue RegexpError => e + # The error messages produced by default are not very helpful, so we + # raise a better one here. We raise the specific error here so its + # message is displayed in the API (where we catch this specific + # error). + raise( + Gitlab::Changelog::Error, + "The regular expression to use for finding the previous tag for a version is invalid: #{e.message}" + ) + end + + def extract_version(string) + matches = version_matcher.match(string) + + return unless matches + + # When using this class for generating changelog data for a range of + # commits, we want to compare against the tag of the last _stable_ + # release; not some random RC that came after that. + return if matches[:pre] + + major = matches[:major] + minor = matches[:minor] + patch = matches[:patch] + build = matches[:meta] + + return unless major && minor && patch + + version = "#{major}.#{minor}.#{patch}" + version += "+#{build}" if build + + version + end end end diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 638e3e57cf64aff73cf9fb523e7b919701b012b4..ced0e313df8d276d52d1c3bf85866b36c4f7f792 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -366,6 +366,9 @@ If the `version` attribute is `2.1.0`, GitLab uses tag `v2.0.0`. And when the version is `1.1.1`, or `1.2.0`, GitLab uses tag v1.1.0. The tag `v1.0.0-pre1` is never used, because pre-release tags are ignored. +The `version` attribute can start with `v`. For example: `v1.0.0`. +The response is the same as for `version` value `1.0.0`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/437616) in GitLab 16.9. + If `from` is unspecified and no tag to use is found, the API produces an error. To solve such an error, you must explicitly specify a value for the `from` attribute. diff --git a/spec/finders/repositories/changelog_tag_finder_spec.rb b/spec/finders/repositories/changelog_tag_finder_spec.rb index cd79beb3e9ee4239eed8c46ccadda645c4a4ebd2..73e302efd27d6fb0164f1d85e26fb7f965097e8c 100644 --- a/spec/finders/repositories/changelog_tag_finder_spec.rb +++ b/spec/finders/repositories/changelog_tag_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Repositories::ChangelogTagFinder do +RSpec.describe Repositories::ChangelogTagFinder, feature_category: :source_code_management do let(:project) { build_stubbed(:project) } let(:finder) { described_class.new(project) } @@ -35,6 +35,10 @@ expect(finder.execute('1.0.0')).to eq(tag4) expect(finder.execute('0.9.0')).to eq(tag6) expect(finder.execute('0.6.0')).to eq(tag7) + + # with v at the beginning + expect(finder.execute('v2.1.0')).to eq(tag3) + expect(finder.execute('wrong_version')).to eq(nil) end end