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 'lib/gitlab/changelog/committer.rb')
-rw-r--r--lib/gitlab/changelog/committer.rb69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/gitlab/changelog/committer.rb b/lib/gitlab/changelog/committer.rb
new file mode 100644
index 00000000000..31661650eff
--- /dev/null
+++ b/lib/gitlab/changelog/committer.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # A class used for committing a release's changelog to a Git repository.
+ class Committer
+ def initialize(project, user)
+ @project = project
+ @user = user
+ end
+
+ # Commits a release's changelog to a file on a branch.
+ #
+ # The `release` argument is a `Gitlab::Changelog::Release` for which to
+ # update the changelog.
+ #
+ # The `file` argument specifies the path to commit the changes to.
+ #
+ # The `branch` argument specifies the branch to commit the changes on.
+ #
+ # The `message` argument specifies the commit message to use.
+ def commit(release:, file:, branch:, message:)
+ # When retrying, we need to reprocess the existing changelog from
+ # scratch, otherwise we may end up throwing away changes. As such, all
+ # the logic is contained within the retry block.
+ Retriable.retriable(on: Error) do
+ commit = Gitlab::Git::Commit.last_for_path(
+ @project.repository,
+ branch,
+ file,
+ literal_pathspec: true
+ )
+
+ content = blob_content(file, commit)
+
+ # If the release has already been added (e.g. concurrently by another
+ # API call), we don't want to add it again.
+ break if content&.match?(release.header_start_pattern)
+
+ service = Files::MultiService.new(
+ @project,
+ @user,
+ commit_message: message,
+ branch_name: branch,
+ start_branch: branch,
+ actions: [
+ {
+ action: content ? 'update' : 'create',
+ content: Generator.new(content.to_s).add(release),
+ file_path: file,
+ last_commit_id: commit&.sha
+ }
+ ]
+ )
+
+ result = service.execute
+
+ raise Error.new(result[:message]) if result[:status] != :success
+ end
+ end
+
+ def blob_content(file, commit = nil)
+ return unless commit
+
+ @project.repository.blob_at(commit.sha, file)&.data
+ end
+ end
+ end
+end