Skip to content

Commit

Permalink
reporter-bugzilla: Reduce number of duplicate bug reports
Browse files Browse the repository at this point in the history
Private bugs are problematic, because we might end up with many
duplicates. We simply don't know if the problem has been
reported already, if the previously reported bug is private.

We are going to open a public bug instead, but the bug description,
which might contain sensitive information, will be private.

We cannot make attachments private though. Attachments in Bugzilla
can be "Red Hat private", but we need users from certain groups
(like "fedora_contrib_private") to have access to them.
Therefore, we are going to create a separate supplementary bug
that will be private and will only contain the attachments.
This supplementary bug will be closed immediately, and the links
to the attachments will be added to the first public bug
in a private comment.

Signed-off-by: Michal Srb <[email protected]>
  • Loading branch information
msrb committed Feb 12, 2024
1 parent 9bc3bc6 commit 87c031f
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 81 deletions.
23 changes: 21 additions & 2 deletions src/client-python/reportclient/internal/bz_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,11 @@ def bug_create(self,
summary: str,
comment: str,
private: bool,
group: List) -> int:
group: List,
status: Optional[str] = None,
resolution: Optional[str] = None,
comment_is_private: bool = False,
extra_private_groups: Optional[List[str]] = None) -> int:
self.logger.debug('-- %s', inspect.getframeinfo(inspect.currentframe()).function)

if group:
Expand All @@ -200,6 +204,15 @@ def bug_create(self,
'status_whiteboard': whiteboard
}

if status and resolution:
data['status'] = status
data['resolution'] = resolution

if comment_is_private:
data['comment_is_private'] = comment_is_private
if extra_private_groups:
data['extra_private_groups'] = extra_private_groups

sub_component = None
if product.startswith('Red Hat Enterprise Linux'):
default_sub_components = {'binutils': 'system-version',
Expand Down Expand Up @@ -270,10 +283,16 @@ def bug_get_comments(self, bug_id: int):

return comments

def bug_add_comment(self, bug_id: int, comment: str):
def bug_add_comment(self, bug_id: int, comment: str, is_private: bool = False, extra_private_groups: Optional[List[str]] = None):
self.logger.debug('-- %s', inspect.getframeinfo(inspect.currentframe()).function)
params = self.params.copy()
params.update({'id': bug_id, 'comment': comment})

if is_private:
params.update({'is_private': True})
if extra_private_groups:
params.update({'extra_private_groups': extra_private_groups})

response = requests.post(os.path.join(self.url, f'rest.cgi/bug/{bug_id}/comment'),
headers=self.headers,
params=params,
Expand Down
159 changes: 80 additions & 79 deletions src/plugins/python/reporter_bugzilla.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,47 +739,65 @@ def log_out(bug_info, rhbz, dump_dir_name):

# }

if existing_id < 0 or rhbz['b_create_private']:
if existing_id < 0:
pf = ProblemFormatter(fmt_file, problem_data, logger)
report = pf.generate_report()
# TODO: if not report (how would that happen?)
if existing_id > 0:
msg = _(
'You have requested to make your data accessible only to a '
'specific group and this bug is a duplicate of bug: '
'{}/{}'
' '
'In case of bug duplicates a new comment is added to the '
'original bug report but access to the comments cannot be '
'restricted to a specific group.'
' '
'Would you like to open a new bug report and close it as '
'DUPLICATE of the original one?'
' '
'Otherwise, the bug reporting procedure will be terminated.'
).format(rhbz['b_bugzilla_url'], existing_id)
if not ask_yes_no(msg):
sys.exit(const.EXIT_CANCEL_BY_USER)
msg = _(
"\nThis is a private, duplicate bug report of bug {}. "
"The report has been created because Bugzilla cannot "
"grant access to a comment for a specific group.\n"
).format(existing_id)
report['text'] += msg
pass

# Create new bug
logger.warning(_('Creating a new bug'))
logger.warning(_('Creating a new bug...'))

if existing_id < 0 <= crossver_id:
report['text'] += f"\nPotential duplicate: bug {crossver_id}\n"

new_id = bz_conn.bug_create(problem_data, rhbz['b_product'], rhbz['b_product_version'],
report['summary'], report['text'], rhbz['b_create_private'],
rhbz['b_private_groups'])
new_id = bz_conn.bug_create(
problem_data,
rhbz['b_product'],
rhbz['b_product_version'],
report['summary'],
report['text'],
False,
None,
comment_is_private = rhbz['b_create_private'],
extra_private_groups = rhbz['b_private_groups']
)
if new_id == -1:
# bug_create logged an error
# bug_create logged the error
sys.exit(1)

attachments_bug_id = new_id

if rhbz['b_create_private']:
# User wants to create a new private bug
text = _(
f"This is a supplementary private bug for uploading attachments for the problem reported in {new_id}. "
f"These attachments are intended to be accessible only to members of the following group(s):\n\n"
f"{",".join(rhbz['b_private_groups'])}"
).format(rhbz['b_private_groups'])
attachments_bug_id = bz_conn.bug_create(
problem_data,
rhbz['b_product'],
rhbz['b_product_version'],
report['summary'],
text,
True,
rhbz['b_private_groups']
)
if attachments_bug_id == -1:
# bug_create logged the error
sys.exit(1)

# Immediately close the supplementary private bug with attachments
update_data = {
'ids': [attachments_bug_id],
'status': 'CLOSED',
'resolution': 'NOTABUG',
'minor_update': True
}
bz_conn.bug_update(attachments_bug_id, update_data)

dump_dir_obj = DumpDir(logger)
dd = dump_dir_obj.dd_opendir(dump_dir_name, 0)
if dd:
Expand All @@ -802,12 +820,37 @@ def log_out(bug_info, rhbz, dump_dir_name):

dump_dir_obj.dd_close(dd)

logger.warning(_('Adding attachments to bug %i'), new_id)
logger.warning(_('Adding attachments to bug %i'), attachments_bug_id)

bug_attachments = []
for attachment in report['attach']:
response = bz_conn.attachment_create_from_problem_data(new_id, attachment, problem_data)
response = bz_conn.attachment_create_from_problem_data(attachments_bug_id, attachment, problem_data)
logger.info("Attached '%s' to bug no. %s with id %s",
attachment, new_id, response.json()['ids'][0])
attachment, attachments_bug_id, response.json()['ids'][0])
if response.status_code == 201:
bug_attachment = {
'name': attachment,
'id': response.json()['ids'][0]
}
bug_attachments.append(bug_attachment)

if rhbz['b_create_private'] and new_id != attachments_bug_id:
text = _(
"Bugzilla does not offer support for private attachments accessible only to specific groups, "
"such as 'fedora_contrib_private'. As a result, a separate private bug has been created, "
"and the following attachments have been added there:\n\n"
)
for bug_attachment in bug_attachments:
# We are hardcoding the URL here. The code already relies on certain "Red Hat Bugzilla API customizations",
# so it wouldn't reliably work with any other Bugzilla instance anyway...
text += f"* {bug_attachment['name']}: https://bugzilla-attachments.redhat.com/attachment.cgi?id={bug_attachment['id']}\n"
# We created a public bug FIXME
bz_conn.bug_add_comment(
new_id,
text,
is_private=rhbz['b_create_private'],
extra_private_groups=rhbz['b_private_groups']
)

# We just created a new bug, let's make sure that we are in CC
bug_info = bz_conn.bug_info(new_id)
Expand All @@ -820,15 +863,6 @@ def log_out(bug_info, rhbz, dump_dir_name):
'bi_status': 'NEW',
'bi_dup_id': -1}

if existing_id >= 0:
logger.warning(_("Closing bug %i as duplicate of bug %i"), new_id, existing_id)
update_data = {'ids': [new_id],
'status': 'CLOSED',
'resolution': 'DUPLICATE',
'dupe_of': existing_id,
'minor_update': True}
bz_conn.bug_update(new_id, update_data)

log_out(bug_info, rhbz, dump_dir_name)

bug_id = existing_id
Expand All @@ -843,30 +877,6 @@ def log_out(bug_info, rhbz, dump_dir_name):
if origin:
bug_info = origin

# Original author's note:
# We used to skip adding the comment to CLOSED bugs:
#
# if (strcmp(bug_info['bi_status'], "CLOSED") != 0)
# {
#
# But that condition has been added without a good explanation of the
# reason for doing so:
#
# ABRT commit 1bf37ad93e87f065347fdb7224578d55cca8d384
#
# - if (bug_id > 0)
# + if (strcmp(bz.bug_status, "CLOSED") != 0)
#
#
# From my point of view, there is no good reason to not add the comment to
# such a bug. The reporter spent several minutes waiting for the backtrace
# and we don't want to make the reporters feel that they spent their time
# in vain and I think that adding comments to already closed bugs doesn't
# hurt the maintainers (at least not me).
#
# Plenty of new comments might convince the maintainer to reconsider the
# bug's status.

# Add user's login to CC if not there already, but only if the login is known
if (
rhbz.get('b_login')
Expand Down Expand Up @@ -901,21 +911,12 @@ def log_out(bug_info, rhbz, dump_dir_name):

if not dup_comment:
logger.warning(_("Adding new comment to bug %d"), bug_info['bi_id'])
bz_conn.bug_add_comment(int(bug_info['bi_id']), bzcomment)

bt = pd_get_item_content(const.FILENAME_BACKTRACE, problem_data)
rating_str = pd_get_item_content(const.FILENAME_RATING, problem_data)
rating = 0
# python doesn't have rating file
if rating_str:
rtg = re.search(r'^\d+', rating_str)
if rtg:
rating = int(rtg.group(0))
if rating > G_MAXUINT64:
logger.error("expected number in range <0, %lu>: '%s'", G_MAXUINT64, rating_str)
if bt and rating > bug_info.get('bi_best_bt_rating', 0):
logger.warning(_("Attaching better backtrace"))
bz_conn.attachment_create(int(bug_info['bi_id']), const.FILENAME_BACKTRACE, True)
bz_conn.bug_add_comment(
int(bug_info['bi_id']),
bzcomment,
is_private = rhbz['b_create_private'],
extra_private_groups = rhbz['b_private_groups']
)
else:
logger.warning(_('Found the same comment in the bug history, not adding a new one'))

Expand Down

0 comments on commit 87c031f

Please sign in to comment.