Beispiel #1
0
    def test_checkwatches_error_recovery(self):
        firefox = getUtility(IProductSet).get(4)
        foobar = getUtility(IPersonSet).get(16)
        params = CreateBugParams(title="test bug one",
                                 comment="test bug one",
                                 owner=foobar,
                                 target=firefox)
        test_bug_one = getUtility(IBugSet).createBug(params)
        params = CreateBugParams(title="test bug two",
                                 comment="test bug two",
                                 owner=foobar,
                                 target=firefox)
        test_bug_two = getUtility(IBugSet).createBug(params)
        self.layer.txn.commit()

        # We use a test bug tracker, which is guaranteed to
        # try and update two bug watches - the first will
        # trigger a DB error, the second updates successfully.
        bug_tracker = TestBugTracker(test_bug_one, test_bug_two)
        bug_watch_updater = TestCheckwatchesMaster(self.layer.txn)
        self.layer.txn.commit()
        bug_watch_updater._updateBugTracker(bug_tracker)
        # We verify that the first bug watch didn't update the status,
        # and the second did.
        for bugtask in test_bug_one.bugtasks:
            self.assertNotEqual(bugtask.status, BugTaskStatus.FIXRELEASED)
        for bugtask in test_bug_two.bugtasks:
            self.assertEqual(bugtask.status, BugTaskStatus.FIXRELEASED)
def bugtarget_filebug(bugtarget, summary, status=None):
    """File a bug as the current user on the bug target and return it."""
    return bugtarget.createBug(
        CreateBugParams(getUtility(ILaunchBag).user,
                        summary,
                        comment=summary,
                        status=status))
Beispiel #3
0
 def createBug(self, owner=None, title="A bug",
               comment="Nothing important.", **kwargs):
     with person_logged_in(owner):
         params = CreateBugParams(
             owner=owner, title=title, comment=comment, **kwargs)
         bug = getUtility(IBugSet).createBug(params)
     return bug
Beispiel #4
0
def _createUbuntuBugTaskLinkedToQuestion():
    """Get the id of an Ubuntu bugtask linked to a question.

    The Ubuntu team is set as the answer contact for Ubuntu, and no-priv
    is used as the submitter..
    """
    login('*****@*****.**')
    sample_person = getUtility(IPersonSet).getByEmail('*****@*****.**')
    ubuntu_team = getUtility(IPersonSet).getByName('ubuntu-team')
    ubuntu_team.addLanguage(getUtility(ILanguageSet)['en'])
    ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
    ubuntu.addAnswerContact(ubuntu_team, ubuntu_team.teamowner)
    ubuntu_question = ubuntu.newQuestion(
        sample_person, "Can't install Ubuntu",
        "I insert the install CD in the CD-ROM drive, but it won't boot.")
    no_priv = getUtility(IPersonSet).getByEmail('*****@*****.**')
    params = CreateBugParams(owner=no_priv,
                             title="Installer fails on a Mac PPC",
                             comment=ubuntu_question.description)
    bug = ubuntu.createBug(params)
    ubuntu_question.linkBug(bug)
    [ubuntu_bugtask] = bug.bugtasks
    login(ANONYMOUS)
    # Remove the notifcations for the newly created question.
    pop_notifications()
    return ubuntu_bugtask.id
Beispiel #5
0
 def test_execute_bug_params_with_rubbish(self):
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = InformationTypeEmailCommand('informationtype', ['rubbish'])
     dummy_event = object()
     self.assertRaises(EmailProcessingError, command.execute, bug_params,
                       dummy_event)
 def test_filters_match_when_bug_is_created(self):
     message = u"this is an unfiltered comment"
     params = CreateBugParams(
         title=u"crashes all the time",
         comment=message, owner=self.submitter,
         status=BugTaskStatus.NEW)
     bug = self.product.createBug(params)
     notification = fetch_notifications(self.subscriber, bug).one()
     self.assertEqual(notification.message.text_contents, message)
Beispiel #7
0
    def execute(self, parsed_msg, filealias):
        """See IBugEmailCommand."""
        self._ensureNumberOfArguments()
        bugid = self.string_args[0]

        if bugid == 'new':
            message = getUtility(IMessageSet).fromEmail(
                parsed_msg.as_string(),
                owner=getUtility(ILaunchBag).user,
                filealias=filealias,
                parsed_message=parsed_msg)
            description = message.text_contents
            if description.strip() == '':
                # The report for a new bug must contain an affects command,
                # since the bug must have at least one task
                raise EmailProcessingError(get_error_message(
                    'no-affects-target-on-submit.txt',
                    error_templates=error_templates),
                                           stop_processing=True)

            # Check the message validator.
            validator = IBugAddForm['comment'].validate
            try:
                validator(description)
            except TooLong:
                raise EmailProcessingError(
                    'The description is too long. If you have lots of '
                    'text to add, use an attachment instead.',
                    stop_processing=True)
            except ValidationError as e:
                # More a just in case than any real expectation of getting
                # something.
                raise EmailProcessingError(str(e), stop_processing=True)

            params = CreateBugParams(msg=message,
                                     title=message.title,
                                     owner=getUtility(ILaunchBag).user)
            return params, None
        else:
            try:
                bugid = int(bugid)
            except ValueError:
                raise EmailProcessingError(
                    get_error_message('bug-argument-mismatch.txt',
                                      error_templates=error_templates))

            try:
                bug = getUtility(IBugSet).get(bugid)
            except NotFoundError:
                bug = None
            if bug is None or not check_permission('launchpad.View', bug):
                raise EmailProcessingError(
                    get_error_message('no-such-bug.txt',
                                      error_templates=error_templates,
                                      bug_id=bugid))
            return bug, None
 def test_filters_do_not_match_when_bug_is_created(self):
     message = u"this is a filtered comment"
     params = CreateBugParams(
         title=u"crashes all the time",
         comment=message, owner=self.submitter,
         status=BugTaskStatus.TRIAGED,
         importance=BugTaskImportance.HIGH)
     bug = self.product.createBug(params)
     notifications = fetch_notifications(self.subscriber, bug)
     self.assertTrue(notifications.is_empty())
Beispiel #9
0
 def test_execute_bug_params(self):
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = TagEmailCommand('tag', ['ui', 'trivial'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertContentEqual(['ui', 'trivial'], bug_params.tags)
     self.assertEqual(dummy_event, event)
Beispiel #10
0
 def test_execute_bug_params(self):
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = SummaryEmailCommand('summary', ['new title'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual('new title', bug_params.title)
     self.assertEqual(dummy_event, event)
Beispiel #11
0
 def test_execute_bug_params(self):
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = PrivateEmailCommand('private', ['yes'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual(InformationType.USERDATA, bug_params.information_type)
     self.assertEqual(dummy_event, event)
Beispiel #12
0
 def test_execute_bug_params_one_subscriber(self):
     user = self.factory.makePerson()
     login_person(user)
     subscriber = self.factory.makePerson()
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = SubscribeEmailCommand('subscribe', [subscriber.name])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertContentEqual([subscriber], bug_params.subscribers)
     self.assertEqual(dummy_event, event)
Beispiel #13
0
 def test_execute_bug_params(self):
     # duplicate does nothing because the is not yet a bug.
     # Any value can be used for the bug is.
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = DuplicateEmailCommand('duplicate', ['non-existent'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual(dummy_event, event)
Beispiel #14
0
 def test_execute_bug_params(self):
     user = self.factory.makePerson()
     login_person(user)
     cve = self.factory.makeCVE('1999-1717')
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = CVEEmailCommand('cve', ['1999-1717'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual(cve, params.cve)
     self.assertEqual(dummy_event, event)
Beispiel #15
0
 def test_execute_bug_params(self):
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(title='bug title', owner=user)
     command = InformationTypeEmailCommand('informationtype',
                                           ['publicsecurity'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual(InformationType.PUBLICSECURITY,
                      bug_params.information_type)
     self.assertTrue(IObjectModifiedEvent.providedBy(event))
def distroseries_sourcepackage_filebug(distroseries, summary, status=None):
    params = CreateBugParams(
        getUtility(ILaunchBag).user,
        summary,
        comment=summary,
        status=status,
        target=distroseries.distribution.getSourcePackage('alsa-utils'))
    bug = distroseries.distribution.createBug(params)
    nomination = bug.addNomination(distroseries.distribution.owner,
                                   distroseries)
    nomination.approve(distroseries.distribution.owner)
    return bug
 def createBug(self, owner, title, description, target,
               information_type=None, tags=None,
               security_related=None, private=None):
     """See `IMaloneApplication`."""
     if (information_type is None
         and (security_related is not None or private is not None)):
         # Adapt the deprecated args to information_type.
         information_type = convert_to_information_type(
             private, security_related)
     params = CreateBugParams(
         title=title, comment=description, owner=owner,
         information_type=information_type, tags=tags, target=target)
     return getUtility(IBugSet).createBug(params)
Beispiel #18
0
    def create_action(self, action, data):
        """Create a Bug from a Question."""
        question = self.context

        with notify_modified(question, ['bugs']):
            params = CreateBugParams(owner=self.user,
                                     title=data['title'],
                                     comment=data['description'])
            bug = question.target.createBug(params)
            question.linkBug(bug, user=self.user)
            bug.subscribe(question.owner, self.user)
        self.request.response.addNotification(
            _('Thank you! Bug #$bugid created.', mapping={'bugid': bug.id}))
        self.next_url = canonical_url(bug)
Beispiel #19
0
 def _createProductBugtask(self, product_name, milestone_name):
     """Create a bugtask for a product, assign the task to a milestone."""
     personset = getUtility(IPersonSet)
     sample_person = personset.getByEmail('*****@*****.**')
     product = getUtility(IProductSet)[product_name]
     milestone = product.getMilestone(milestone_name)
     params = CreateBugParams(title='Milestone test bug for %s' %
                              product_name,
                              comment='comment',
                              owner=sample_person,
                              status=BugTaskStatus.CONFIRMED)
     bug = product.createBug(params)
     [bugtask] = bug.bugtasks
     bugtask.milestone = milestone
Beispiel #20
0
    def importBug(self, external_bugtracker, bugtracker, bug_target,
                  remote_bug):
        """Import a remote bug into Launchpad.

        :param external_bugtracker: An ISupportsBugImport, which talks
            to the external bug tracker.
        :param bugtracker: An IBugTracker, to which the created bug
            watch will be linked.
        :param bug_target: An IBugTarget, to which the created bug will
            be linked.
        :param remote_bug: The remote bug id as a string.

        :return: The created Launchpad bug.
        """
        assert IDistribution.providedBy(bug_target), (
            'Only imports of bugs for a distribution is implemented.')
        reporter_name, reporter_email = (
            external_bugtracker.getBugReporter(remote_bug))
        reporter = getUtility(IPersonSet).ensurePerson(
            reporter_email, reporter_name, PersonCreationRationale.BUGIMPORT,
            comment='when importing bug #%s from %s' % (
                remote_bug, external_bugtracker.baseurl))
        package_name = external_bugtracker.getBugTargetName(remote_bug)
        package = bug_target.getSourcePackage(package_name)
        if package is not None:
            bug_target = package
        else:
            self.warning(
                'Unknown %s package (#%s at %s): %s' % (
                    bug_target.name, remote_bug,
                    external_bugtracker.baseurl, package_name))
        summary, description = (
            external_bugtracker.getBugSummaryAndDescription(remote_bug))
        bug = bug_target.createBug(
            CreateBugParams(
                reporter, summary, description, subscribe_owner=False,
                filed_by=getUtility(ILaunchpadCelebrities).bug_watch_updater))
        [added_task] = bug.bugtasks
        bug_watch = getUtility(IBugWatchSet).createBugWatch(
            bug=bug,
            owner=getUtility(ILaunchpadCelebrities).bug_watch_updater,
            bugtracker=bugtracker, remotebug=remote_bug)

        added_task.bugwatch = bug_watch
        # Need to flush databse updates, so that the bug watch knows it
        # is linked from a bug task.
        flush_database_updates()

        return bug
Beispiel #21
0
 def test_execute_bug_params_distribution(self):
     user = self.factory.makePerson()
     login_person(user)
     distribution = self.factory.makeDistribution(name='fnord')
     message = self.factory.makeMessage(subject='bug title',
                                        content='borked\n affects fnord')
     command = AffectsEmailCommand('affects', ['fnord'])
     bug_params = CreateBugParams(title='bug title',
                                  msg=message,
                                  owner=user)
     bugtask, bugtask_event, bug_event = command.execute(bug_params, None)
     self.assertEqual(distribution, bugtask.target)
     self.assertEqual('bug title', bugtask.bug.title)
     self.assertTrue(IObjectCreatedEvent.providedBy(bugtask_event))
     self.assertTrue(IObjectCreatedEvent.providedBy(bug_event))
Beispiel #22
0
def create_bug_from_strings(
    distribution, sourcepackagename, owner, summary, description,
    status=None):
    """Create and return a bug."""
    distroset = getUtility(IDistributionSet)
    distribution = distroset.getByName(distribution)

    personset = getUtility(IPersonSet)
    owner = personset.getByName(owner)

    bugset = getUtility(IBugSet)
    params = CreateBugParams(
        owner, summary, description, status=status,
        target=distribution.getSourcePackage(sourcepackagename))
    return bugset.createBug(params)
Beispiel #23
0
 def test_execute_bug_params_with_security(self):
     # BugSet.createBug() requires new security bugs to be private.
     user = self.factory.makePerson()
     login_person(user)
     bug_params = CreateBugParams(
         title='bug title',
         owner=user,
         information_type=InformationType.PRIVATESECURITY)
     command = PrivateEmailCommand('private', ['no'])
     dummy_event = object()
     params, event = command.execute(bug_params, dummy_event)
     self.assertEqual(bug_params, params)
     self.assertEqual(InformationType.PRIVATESECURITY,
                      bug_params.information_type)
     self.assertEqual(dummy_event, event)
Beispiel #24
0
 def test_execute_bug_params_productseries(self):
     product = self.factory.makeProduct(name='fnord')
     login_person(product.owner)
     series = self.factory.makeProductSeries(name='pting', product=product)
     message = self.factory.makeMessage(
         subject='bug title', content='borked\n affects fnord/pting')
     command = AffectsEmailCommand('affects', ['fnord/pting'])
     bug_params = CreateBugParams(title='bug title',
                                  msg=message,
                                  owner=product.owner)
     bugtask, bugtask_event, bug_event = command.execute(bug_params, None)
     self.assertEqual(series, bugtask.target)
     self.assertEqual('bug title', bugtask.bug.title)
     self.assertEqual(2, len(bugtask.bug.bugtasks))
     self.assertTrue(IObjectCreatedEvent.providedBy(bugtask_event))
     self.assertTrue(IObjectCreatedEvent.providedBy(bug_event))
Beispiel #25
0
    def create_action(self, action, data):
        """Create a Bug from a Question."""
        question = self.context

        unmodifed_question = Snapshot(question, providing=providedBy(question))
        params = CreateBugParams(owner=self.user,
                                 title=data['title'],
                                 comment=data['description'])
        bug = question.target.createBug(params)
        question.linkBug(bug)
        bug.subscribe(question.owner, self.user)
        bug_added_event = ObjectModifiedEvent(question, unmodifed_question,
                                              ['bugs'])
        notify(bug_added_event)
        self.request.response.addNotification(
            _('Thank you! Bug #$bugid created.', mapping={'bugid': bug.id}))
        self.next_url = canonical_url(bug)
 def test_manage_notifications_message_is_included(self):
     # Set up a subscription to a product.
     subscriber = self.factory.makePerson()
     submitter = self.factory.makePerson()
     product = self.factory.makeProduct(
         bug_supervisor=submitter)
     product.addSubscription(subscriber, subscriber)
     # Create a bug that will match the subscription.
     bug = product.createBug(CreateBugParams(
         title=self.factory.getUniqueString(),
         comment=self.factory.getUniqueString(),
         owner=submitter))
     notification = fetch_notifications(subscriber, bug).one()
     _, _, (message,) = construct_email_notifications([notification])
     payload = message.get_payload()
     self.assertThat(payload, Contains(
         'To manage notifications about this bug go to:\nhttp://'))
Beispiel #27
0
 def _createProductSeriesBugtask(self, product_name, product_series_name,
                                 milestone_name):
     """Create a bugtask for a productseries, assign it to a milestone."""
     personset = getUtility(IPersonSet)
     sample_person = personset.getByEmail('*****@*****.**')
     product = getUtility(IProductSet)[product_name]
     series = product.getSeries(product_series_name)
     milestone = product.getMilestone(milestone_name)
     params = CreateBugParams(title='Milestone test bug for %s series' %
                              product_name,
                              comment='comment',
                              owner=sample_person,
                              status=BugTaskStatus.CONFIRMED)
     bug = product.createBug(params)
     getUtility(IBugTaskSet).createTask(bug, sample_person, series)
     for bugtask in bug.bugtasks:
         if bugtask.productseries is not None:
             bugtask.milestone = milestone
Beispiel #28
0
 def test_execute_bug_params_distroseries_sourcepackage(self):
     distribution = self.factory.makeDistribution(name='fnord')
     login_person(distribution.owner)
     series = self.factory.makeDistroSeries(name='pting',
                                            distribution=distribution)
     package = self.factory.makeSourcePackage(sourcepackagename='snarf',
                                              distroseries=series,
                                              publish=True)
     message = self.factory.makeMessage(
         subject='bug title', content='borked\n affects fnord/pting/snarf')
     command = AffectsEmailCommand('affects', ['fnord/pting/snarf'])
     bug_params = CreateBugParams(title='bug title',
                                  msg=message,
                                  owner=distribution.owner)
     bugtask, bugtask_event, bug_event = command.execute(bug_params, None)
     self.assertEqual(package, bugtask.target)
     self.assertEqual('bug title', bugtask.bug.title)
     self.assertEqual(2, len(bugtask.bug.bugtasks))
     self.assertTrue(IObjectCreatedEvent.providedBy(bugtask_event))
     self.assertTrue(IObjectCreatedEvent.providedBy(bug_event))
Beispiel #29
0
def create_old_bug(
    title, days_old, target, status=BugTaskStatus.INCOMPLETE,
    with_message=True, external_bugtracker=None, assignee=None,
    milestone=None, duplicateof=None):
    """Create an aged bug.

    :title: A string. The bug title for testing.
    :days_old: An int. The bug's age in days.
    :target: A BugTarget. The bug's target.
    :status: A BugTaskStatus. The status of the bug's single bugtask.
    :with_message: A Bool. Whether to create a reply message.
    :external_bugtracker: An external bug tracker which is watched for this
        bug.
    """
    no_priv = getUtility(IPersonSet).getByEmail('*****@*****.**')
    params = CreateBugParams(
        owner=no_priv, title=title, comment='Something is broken.')
    bug = target.createBug(params)
    if duplicateof is not None:
        bug.markAsDuplicate(duplicateof)
    sample_person = getUtility(IPersonSet).getByEmail('*****@*****.**')
    if with_message is True:
        bug.newMessage(
            owner=sample_person, subject='Something is broken.',
            content='Can you provide more information?')
    bugtask = bug.bugtasks[0]
    bugtask.transitionToStatus(
        status, sample_person)
    if assignee is not None:
        bugtask.transitionToAssignee(assignee)
    bugtask.milestone = milestone
    if external_bugtracker is not None:
        getUtility(IBugWatchSet).createBugWatch(bug=bug, owner=sample_person,
            bugtracker=external_bugtracker, remotebug='1234')
    date = datetime.now(UTC) - timedelta(days=days_old)
    removeSecurityProxy(bug).date_last_updated = date
    return bugtask
Beispiel #30
0
    def importBug(self, bugnode):
        assert not self.haveImportedBug(bugnode), (
            'the bug has already been imported')
        bug_id = int(bugnode.get('id'))

        self.logger.info('Handling bug %d', bug_id)

        comments = get_all(bugnode, 'comment')

        owner = self.getPerson(get_element(bugnode, 'reporter'))
        datecreated = parse_date(get_value(bugnode, 'datecreated'))
        title = get_value(bugnode, 'title')

        private = get_value(bugnode, 'private') == 'True'
        security_related = get_value(bugnode, 'security_related') == 'True'
        information_type = convert_to_information_type(private,
                                                       security_related)

        if owner is None:
            owner = self.bug_importer
        commentnode = comments.pop(0)
        msg = self.createMessage(commentnode, defaulttitle=title)

        bug = self.product.createBug(
            CreateBugParams(msg=msg,
                            datecreated=datecreated,
                            title=title,
                            information_type=information_type,
                            owner=owner))
        bugtask = bug.bugtasks[0]
        self.logger.info('Creating Launchpad bug #%d', bug.id)

        # Remaining setup for first comment
        self.createAttachments(bug, msg, commentnode)
        bug.findCvesInText(msg.text_contents, bug.owner)

        # Process remaining comments
        for commentnode in comments:
            msg = self.createMessage(commentnode,
                                     defaulttitle=bug.followup_subject())
            bug.linkMessage(msg)
            self.createAttachments(bug, msg, commentnode)

        bug.name = get_value(bugnode, 'nickname')
        description = get_value(bugnode, 'description')
        if description:
            bug.description = description

        for cvenode in get_all(bugnode, 'cves/cve'):
            cve = getUtility(ICveSet)[get_text(cvenode)]
            if cve is None:
                raise BugXMLSyntaxError('Unknown CVE: %s' % get_text(cvenode))
            bug.linkCVE(cve, self.bug_importer, check_permissions=False)

        tags = []
        for tagnode in get_all(bugnode, 'tags/tag'):
            tags.append(get_text(tagnode))
        bug.tags = tags

        # Create bugwatches
        bugwatchset = getUtility(IBugWatchSet)
        for watchnode in get_all(bugnode, 'bugwatches/bugwatch'):
            try:
                bugtracker, remotebug = bugwatchset.extractBugTrackerAndBug(
                    watchnode.get('href'))
            except NoBugTrackerFound as exc:
                self.logger.debug('Registering bug tracker for %s',
                                  exc.base_url)
                bugtracker = getUtility(IBugTrackerSet).ensureBugTracker(
                    exc.base_url, self.bug_importer, exc.bugtracker_type)
                remotebug = exc.remote_bug
            bugwatchset.createBugWatch(bug, self.bug_importer, bugtracker,
                                       remotebug)

        for subscribernode in get_all(bugnode, 'subscriptions/subscriber'):
            person = self.getPerson(subscribernode)
            if person is not None:
                bug.subscribe(person, owner)

        # set up bug task
        bugtask.datecreated = datecreated
        bugtask.transitionToImportance(
            get_enum_value(BugTaskImportance, get_value(bugnode,
                                                        'importance')),
            self.bug_importer)
        bugtask.transitionToStatus(
            get_enum_value(BugTaskStatus, get_value(bugnode, 'status')),
            self.bug_importer)
        bugtask.transitionToAssignee(
            self.getPerson(get_element(bugnode, 'assignee')))
        bugtask.milestone = self.getMilestone(get_value(bugnode, 'milestone'))

        # Make a note of the import in the activity log:
        getUtility(IBugActivitySet).new(bug=bug.id,
                                        datechanged=UTC_NOW,
                                        person=self.bug_importer,
                                        whatchanged='bug',
                                        message='Imported external bug #%s' %
                                        bug_id)

        self.handleDuplicate(bug, bug_id, get_value(bugnode, 'duplicateof'))
        self.bug_id_map[bug_id] = bug.id

        # clear any pending bug notifications
        bug.expireNotifications()
        return bug