Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/repositories/changelog_service.rb')
-rw-r--r--app/services/repositories/changelog_service.rb115
1 files changed, 115 insertions, 0 deletions
diff --git a/app/services/repositories/changelog_service.rb b/app/services/repositories/changelog_service.rb
new file mode 100644
index 00000000000..96a63865a49
--- /dev/null
+++ b/app/services/repositories/changelog_service.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+module Repositories
+ # A service class for generating a changelog section.
+ class ChangelogService
+ DEFAULT_TRAILER = 'Changelog'
+ DEFAULT_FILE = 'CHANGELOG.md'
+
+ # The `project` specifies the `Project` to generate the changelog section
+ # for.
+ #
+ # The `user` argument specifies a `User` to use for committing the changes
+ # to the Git repository.
+ #
+ # The `version` arguments must be a version `String` using semantic
+ # versioning as the format.
+ #
+ # The arguments `from` and `to` must specify a Git ref or SHA to use for
+ # fetching the commits to include in the changelog. The SHA/ref set in the
+ # `from` argument isn't included in the list.
+ #
+ # The `date` argument specifies the date of the release, and defaults to the
+ # current time/date.
+ #
+ # The `branch` argument specifies the branch to commit the changes to. The
+ # branch must already exist.
+ #
+ # The `trailer` argument is the Git trailer to use for determining what
+ # commits to include in the changelog.
+ #
+ # The `file` arguments specifies the name/path of the file to commit the
+ # changes to. If the file doesn't exist, it's created automatically.
+ #
+ # The `message` argument specifies the commit message to use when committing
+ # the changelog changes.
+ #
+ # rubocop: disable Metrics/ParameterLists
+ def initialize(
+ project,
+ user,
+ version:,
+ to:,
+ from: nil,
+ date: DateTime.now,
+ branch: project.default_branch_or_master,
+ trailer: DEFAULT_TRAILER,
+ file: DEFAULT_FILE,
+ message: "Add changelog for version #{version}"
+ )
+ @project = project
+ @user = user
+ @version = version
+ @from = from
+ @to = to
+ @date = date
+ @branch = branch
+ @trailer = trailer
+ @file = file
+ @message = message
+ end
+ # rubocop: enable Metrics/ParameterLists
+
+ def execute
+ from = start_of_commit_range
+
+ # For every entry we want to only include the merge request that
+ # originally introduced the commit, which is the oldest merge request that
+ # contains the commit. We fetch there merge requests in batches, reducing
+ # the number of SQL queries needed to get this data.
+ mrs_finder = MergeRequests::OldestPerCommitFinder.new(@project)
+ config = Gitlab::Changelog::Config.from_git(@project)
+ release = Gitlab::Changelog::Release
+ .new(version: @version, date: @date, config: config)
+
+ commits =
+ CommitsWithTrailerFinder.new(project: @project, from: from, to: @to)
+
+ commits.each_page(@trailer) do |page|
+ mrs = mrs_finder.execute(page)
+
+ # Preload the authors. This ensures we only need a single SQL query per
+ # batch of commits, instead of needing a query for every commit.
+ page.each(&:lazy_author)
+
+ page.each do |commit|
+ release.add_entry(
+ title: commit.title,
+ commit: commit,
+ category: commit.trailers.fetch(@trailer),
+ author: commit.author,
+ merge_request: mrs[commit.id]
+ )
+ end
+ end
+
+ Gitlab::Changelog::Committer
+ .new(@project, @user)
+ .commit(release: release, file: @file, branch: @branch, message: @message)
+ end
+
+ def start_of_commit_range
+ return @from if @from
+
+ if (prev_tag = PreviousTagFinder.new(@project).execute(@version))
+ return prev_tag.target_commit.id
+ end
+
+ raise(
+ Gitlab::Changelog::Error,
+ 'The commit start range is unspecified, and no previous tag ' \
+ 'could be found to use instead'
+ )
+ end
+ end
+end