Commit 21a1a528 authored by allison.browne's avatar allison.browne

Add uniqueness validation to sentry_issue_identifer

Add a uniquness validation to the SentryIssue table on the
sentry_issue_identifier scoped to the project. Change the SentryFinder
to be determanistic by adding an order to the query.
parent 9fe418ba
...@@ -5,13 +5,22 @@ class SentryIssue < ApplicationRecord ...@@ -5,13 +5,22 @@ class SentryIssue < ApplicationRecord
validates :issue, uniqueness: true, presence: true validates :issue, uniqueness: true, presence: true
validates :sentry_issue_identifier, presence: true validates :sentry_issue_identifier, presence: true
validate :ensure_sentry_issue_identifier_is_unique_per_project
after_create_commit :enqueue_sentry_sync_job after_create_commit :enqueue_sentry_sync_job
def self.for_project_and_identifier(project, identifier) def self.for_project_and_identifier(project, identifier)
joins(:issue) joins(:issue)
.where(issues: { project_id: project.id }) .where(issues: { project_id: project.id })
.find_by_sentry_issue_identifier(identifier) .where(sentry_issue_identifier: identifier)
.order('issues.created_at').last
end
def ensure_sentry_issue_identifier_is_unique_per_project
if issue && self.class.for_project_and_identifier(issue.project, sentry_issue_identifier).present?
# Custom message because field is hidden
errors.add(:_, _('is already associated to a GitLab Issue. New issue will not be associated.'))
end
end end
def enqueue_sentry_sync_job def enqueue_sentry_sync_job
......
...@@ -22692,6 +22692,9 @@ msgstr "" ...@@ -22692,6 +22692,9 @@ msgstr ""
msgid "is" msgid "is"
msgstr "" msgstr ""
msgid "is already associated to a GitLab Issue. New issue will not be associated."
msgstr ""
msgid "is an invalid IP address range" msgid "is an invalid IP address range"
msgstr "" msgstr ""
......
...@@ -13,6 +13,20 @@ describe SentryIssue do ...@@ -13,6 +13,20 @@ describe SentryIssue do
it { is_expected.to validate_presence_of(:issue) } it { is_expected.to validate_presence_of(:issue) }
it { is_expected.to validate_uniqueness_of(:issue) } it { is_expected.to validate_uniqueness_of(:issue) }
it { is_expected.to validate_presence_of(:sentry_issue_identifier) } it { is_expected.to validate_presence_of(:sentry_issue_identifier) }
it 'allows duplicated sentry_issue_identifier' do
duplicate_sentry_issue = build(:sentry_issue, sentry_issue_identifier: sentry_issue.sentry_issue_identifier)
expect(duplicate_sentry_issue).to be_valid
end
it 'validates uniqueness of sentry_issue_identifier per project' do
second_issue = create(:issue, project: sentry_issue.issue.project)
duplicate_sentry_issue = build(:sentry_issue, issue: second_issue, sentry_issue_identifier: sentry_issue.sentry_issue_identifier)
expect(duplicate_sentry_issue).to be_invalid
expect(duplicate_sentry_issue.errors.full_messages.first).to include('is already associated')
end
end end
describe 'callbacks' do describe 'callbacks' do
...@@ -28,13 +42,16 @@ describe SentryIssue do ...@@ -28,13 +42,16 @@ describe SentryIssue do
end end
describe '.for_project_and_identifier' do describe '.for_project_and_identifier' do
let!(:sentry_issue) { create(:sentry_issue) } it 'finds the most recent per project and sentry_issue_identifier' do
let(:project) { sentry_issue.issue.project } sentry_issue = create(:sentry_issue)
let(:identifier) { sentry_issue.sentry_issue_identifier } create(:sentry_issue)
let!(:second_sentry_issue) { create(:sentry_issue) } project = sentry_issue.issue.project
sentry_issue_3 = build(:sentry_issue, issue: create(:issue, project: project), sentry_issue_identifier: sentry_issue.sentry_issue_identifier)
sentry_issue_3.save(validate: false)
subject { described_class.for_project_and_identifier(project, identifier) } result = described_class.for_project_and_identifier(project, sentry_issue.sentry_issue_identifier)
it { is_expected.to eq(sentry_issue) } expect(result).to eq(sentry_issue_3)
end
end end
end 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