Module: Gitlab::Import::MergeRequestHelpers
- Includes:
- DatabaseHelpers
- Included in:
- BitbucketServerImport::Importers::PullRequestNotes::ApprovedEvent, BitbucketServerImport::Importers::PullRequestNotes::DeclinedEvent, BitbucketServerImport::Importers::PullRequestNotes::MergeEvent, GithubImport::Importer::PullRequestImporter, GithubImport::Importer::PullRequests::ReviewImporter, MergeRequestCreator
- Defined in:
- lib/gitlab/import/merge_request_helpers.rb
Instance Method Summary collapse
- #add_approval_system_note!(project_id, merge_request_id, user_id, submitted_at) ⇒ Object
- #create_approval!(project_id, merge_request_id, user_id, submitted_at) ⇒ Object
-
#create_merge_request_metrics(attributes) ⇒ Object
MergeRequest::Metrics.
-
#create_merge_request_without_hooks(project, attributes, iid) ⇒ Object
rubocop: disable CodeReuse/ActiveRecord.
- #create_reviewer!(merge_request_id, user_id, submitted_at) ⇒ Object
- #insert_merge_request_reviewers(merge_request, reviewers) ⇒ Object
-
#insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false) ⇒ Object
rubocop: enable CodeReuse/ActiveRecord.
Methods included from DatabaseHelpers
Instance Method Details
#add_approval_system_note!(project_id, merge_request_id, user_id, submitted_at) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 107 def add_approval_system_note!(project_id, merge_request_id, user_id, submitted_at) attributes = { importing: true, noteable_id: merge_request_id, noteable_type: 'MergeRequest', project_id: project_id, author_id: user_id, note: 'approved this merge request', system: true, system_note_metadata: SystemNoteMetadata.new(action: 'approved'), created_at: submitted_at, updated_at: submitted_at } Note.create!(attributes) end |
#create_approval!(project_id, merge_request_id, user_id, submitted_at) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 89 def create_approval!(project_id, merge_request_id, user_id, submitted_at) approval = Approval.create( merge_request_id: merge_request_id, user_id: user_id, created_at: submitted_at, updated_at: submitted_at, importing: true ) return unless approval.persisted? note = add_approval_system_note!(project_id, merge_request_id, user_id, submitted_at) [approval, note] rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation # Multiple approvals mapped to the same user (e.g. personal namespace owner) can cause validation race condition end |
#create_merge_request_metrics(attributes) ⇒ Object
Returns MergeRequest::Metrics.
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 10 def create_merge_request_metrics(attributes) retries ||= 0 metric = MergeRequest::Metrics.find_or_initialize_by(merge_request: merge_request) # rubocop: disable CodeReuse/ActiveRecord -- no need to move this to ActiveRecord model metric.update(attributes) metric rescue ActiveRecord::RecordNotUnique => e # Multiple jobs may attempt to create the metrics simultaneously sleep 1 retries += 1 retry if retries < 5 raise e end |
#create_merge_request_without_hooks(project, attributes, iid) ⇒ Object
rubocop: disable CodeReuse/ActiveRecord
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 25 def create_merge_request_without_hooks(project, attributes, iid) # This work must be wrapped in a transaction as otherwise we can leave # behind incomplete data in the event of an error. This can then lead # to duplicate key errors when jobs are retried. MergeRequest.transaction do # When creating merge requests there are a lot of hooks that may # run, for many different reasons. Many of these hooks (e.g. the # ones used for rendering Markdown) are completely unnecessary and # may even lead to transaction timeouts. # # To ensure importing pull requests has a minimal impact and can # complete in a reasonable time we bypass all the hooks by inserting # the row and then retrieving it. We then only perform the # additional work that is strictly necessary. merge_request_id = insert_and_return_id(attributes, project.merge_requests) merge_request = project.merge_requests.reset.find(merge_request_id) [merge_request, false] end rescue ActiveRecord::InvalidForeignKey # It's possible the project has been deleted since scheduling this # job. In this case we'll just skip creating the merge request. [] rescue ActiveRecord::RecordNotUnique # It's possible we previously created the MR, but failed when updating # the Git data. In this case we'll just continue working on the # existing row. [project.merge_requests.find_by(iid: iid), true] end |
#create_reviewer!(merge_request_id, user_id, submitted_at) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 124 def create_reviewer!(merge_request_id, user_id, submitted_at) ::MergeRequestReviewer.create!( merge_request_id: merge_request_id, user_id: user_id, state: ::MergeRequestReviewer.states['reviewed'], created_at: submitted_at ) rescue ActiveRecord::RecordNotUnique # multiple reviews from single person could make a SQL concurrency issue here nil end |
#insert_merge_request_reviewers(merge_request, reviewers) ⇒ Object
82 83 84 85 86 87 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 82 def insert_merge_request_reviewers(merge_request, reviewers) return unless reviewers.present? rows = reviewers.map { |reviewer_id| { merge_request_id: merge_request.id, user_id: reviewer_id } } MergeRequestReviewer.insert_all(rows) end |
#insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false) ⇒ Object
rubocop: enable CodeReuse/ActiveRecord
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/gitlab/import/merge_request_helpers.rb', line 57 def insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists = false) # These fields are set so we can create the correct merge request # diffs. merge_request.source_branch_sha = source_branch_sha merge_request.target_branch_sha = target_branch_sha merge_request.keep_around_commit # We force to recreate all diffs to replace all existing data # We use `.all` as otherwise `dependent: :nullify` (the default) # takes an effect merge_request.merge_request_diffs.all.delete_all if already_exists # MR diffs normally use an "after_save" hook to pull data from Git. # All of this happens in the transaction started by calling # create/save/etc. This in turn can lead to these transactions being # held open for much longer than necessary. To work around this we # first save the diff, then populate it. diff = merge_request.merge_request_diffs.build diff.importing = true diff.save diff.save_git_content diff.set_as_latest_diff end |