Exemplo n.º 1
0
    def test_no_fedmsgs(self, mock_fedmsg_publish):
        """Assert nothing happens if messages are not explicitly published."""
        session = Session()
        session.add(models.Package(name=u'ejabberd'))
        session.commit()

        self.assertEqual(0, mock_fedmsg_publish.call_count)
Exemplo n.º 2
0
def dequeue_stable():
    """Convert all batched requests to stable requests."""
    initialize_db(config.config)
    buildsys.setup_buildsystem(config.config)
    db = Session()

    try:
        batched = db.query(models.Update).filter_by(
            request=models.UpdateRequest.batched).all()
        for update in batched:
            try:
                update.set_request(db, models.UpdateRequest.stable, u'bodhi')
                db.commit()
            except Exception as e:
                print('Unable to stabilize {}: {}'.format(
                    update.alias, str(e)))
                db.rollback()
                msg = u"Bodhi is unable to request this update for stabilization: {}"
                update.comment(db, msg.format(str(e)), author=u'bodhi')
                db.commit()
    except Exception as e:
        print(str(e))
        sys.exit(1)
    finally:
        Session.remove()
Exemplo n.º 3
0
def main():
    """Check the enforced policies by Greenwave for each open update."""
    session = Session()

    updates = models.Update.query.filter(
        models.Update.status.in_(
            [models.UpdateStatus.pending, models.UpdateStatus.testing])
    ).filter(models.Update.release_id == models.Release.id).filter(
        models.Release.state.in_([
            models.ReleaseState.current, models.ReleaseState.pending,
            models.ReleaseState.frozen
        ])
    ).order_by(
        # Check the older updates first so there is more time for the newer to
        # get their test results
        models.Update.id.asc())

    for update in updates:
        try:
            update.update_test_gating_status()
            session.commit()
        except Exception:
            # If there is a problem talking to Greenwave server, print the error.
            log.exception(
                f"There was an error checking the policy for {update.alias}")
            session.rollback()
Exemplo n.º 4
0
    def __call__(self):
        """
        Manage a database Session object for the life of the context.

        Yields a database Session object, then either commits the tranaction if there were no
        Exceptions or rolls back the transaction. In either case, it also will close and remove the
        Session.
        """
        session = Session()
        try:
            yield session
            session.commit()
        except Exception as e:
            # It is possible for session.rolback() to raise Exceptions, so we will wrap it in an
            # Exception handler as well so we can log the rollback failure and still raise the
            # original Exception.
            try:
                session.rollback()
            except Exception:
                log.exception(
                    'An Exception was raised while rolling back a transaction.'
                )
            raise e
        finally:
            session.close()
            Session.remove()
Exemplo n.º 5
0
def check():
    """Check the enforced policies by Greenwave for each open update."""
    initialize_db(config.config)
    session = Session()

    updates = models.Update.query.filter(
        models.Update.status.in_(
            [models.UpdateStatus.pending, models.UpdateStatus.testing])
    ).filter(
        models.Update.release_id == models.Release.id
    ).filter(
        models.Release.state.in_(
            [models.ReleaseState.current, models.ReleaseState.pending])
    ).order_by(
        # Check the older updates first so there is more time for the newer to
        # get their test results
        models.Update.id.asc()
    )

    for update in updates:
        try:
            update.update_test_gating_status()
            session.commit()
        except Exception as e:
            # If there is a problem talking to Greenwave server, print the error.
            click.echo(str(e))
            session.rollback()
Exemplo n.º 6
0
 def test_repeated_commit(self, mock_fedmsg_publish):
     """Assert queued fedmsgs are cleared between commits."""
     session = Session()
     notifications.publish('demo.topic', {'new': 'package'})
     session.commit()
     session.commit()
     mock_fedmsg_publish.assert_called_once_with(topic='demo.topic',
                                                 msg={'new': 'package'})
Exemplo n.º 7
0
 def test_single_topic_one_message(self, mock_fedmsg_publish):
     """Assert a single message for a single topic is published."""
     session = Session()
     session.add(models.Package(name=u'ejabberd'))
     notifications.publish('demo.topic', {'new': 'package'})
     session.commit()
     mock_fedmsg_publish.assert_called_once_with(topic='demo.topic',
                                                 msg={'new': 'package'})
Exemplo n.º 8
0
 def test_empty_commit(self, mock_fedmsg_publish):
     """Assert calling commit on a session with no changes still triggers fedmsgs."""
     # Ensure nothing at all is in our session
     Session.remove()
     session = Session()
     notifications.publish('demo.topic', {'new': 'package'})
     session.commit()
     mock_fedmsg_publish.assert_called_once_with(topic='demo.topic',
                                                 msg={'new': 'package'})
Exemplo n.º 9
0
def main(argv=sys.argv):
    """
    Remove the pending and testing tags from branched updates.

    Args:
        argv (list): The arguments passed to the script. Defaults to sys.argv.
    """
    if len(argv) != 2:
        usage(argv)

    config_uri = argv[1]

    setup_logging(config_uri)
    log = logging.getLogger(__name__)

    settings = get_appsettings(config_uri)
    initialize_db(settings)
    db = Session()
    koji = buildsys.get_session()
    one_day = timedelta(days=1)
    now = datetime.utcnow()

    try:
        for release in db.query(Release).filter_by(
                state=ReleaseState.pending).all():
            log.info(release.name)
            for update in db.query(Update).filter_by(
                    release=release, status=UpdateStatus.stable).all():
                if now - update.date_stable > one_day:
                    for build in update.builds:
                        tags = build.get_tags()
                        stable_tag = release.dist_tag
                        testing_tag = release.testing_tag
                        pending_signing_tag = release.pending_signing_tag
                        pending_testing_tag = release.pending_testing_tag
                        if stable_tag not in tags:
                            log.error('%s not tagged as stable %s' %
                                      (build.nvr, tags))
                            continue
                        if testing_tag in tags:
                            log.info('Removing %s from %s' %
                                     (testing_tag, build.nvr))
                            koji.untagBuild(testing_tag, build.nvr)
                        if pending_signing_tag in tags:
                            log.info('Removing %s from %s' %
                                     (pending_signing_tag, build.nvr))
                            koji.untagBuild(pending_signing_tag, build.nvr)
                        if pending_testing_tag in tags:
                            log.info('Removing %s from %s' %
                                     (pending_testing_tag, build.nvr))
                            koji.untagBuild(pending_testing_tag, build.nvr)
        db.commit()
    except Exception as e:
        log.error(e)
        db.rollback()
        Session.remove()
        sys.exit(1)
Exemplo n.º 10
0
    def test_commit_aborted(self, mock_fedmsg_publish):
        """Assert that when commits are aborted, messages aren't sent."""
        session = Session()
        session.add(models.Package(name=u'ejabberd'))
        session.commit()

        session.add(models.Package(name=u'ejabberd'))
        notifications.publish('demo.topic', {'new': 'package'})
        self.assertRaises(exc.IntegrityError, session.commit)
        self.assertEqual(0, mock_fedmsg_publish.call_count)
Exemplo n.º 11
0
def main():
    """Wrap ``expire_overrides()``, catching exceptions."""
    db = Session()
    try:
        expire_overrides(db)
        db.commit()
    except Exception:
        log.exception("There was an error expiring overrides")
        db.rollback()
        Session.remove()
Exemplo n.º 12
0
 def test_multiple_topics(self, mock_fedmsg_publish):
     """Assert messages with different topics are sent."""
     session = Session()
     notifications.publish('demo.topic', {'new': 'package'})
     notifications.publish('other.topic', {'newer': 'packager'})
     session.commit()
     self.assertEqual(2, mock_fedmsg_publish.call_count)
     mock_fedmsg_publish.assert_any_call(topic='demo.topic',
                                         msg={'new': 'package'})
     mock_fedmsg_publish.assert_any_call(topic='other.topic',
                                         msg={'newer': 'packager'})
Exemplo n.º 13
0
 def test_single_topic_many_messages(self, mock_fedmsg_publish):
     """Assert many messages for a single topic are sent."""
     session = Session()
     notifications.publish('demo.topic', {'new': 'package'})
     notifications.publish('demo.topic', {'newer': 'packager'})
     session.commit()
     self.assertEqual(2, mock_fedmsg_publish.call_count)
     mock_fedmsg_publish.assert_any_call(topic='demo.topic',
                                         msg={'new': 'package'})
     mock_fedmsg_publish.assert_any_call(topic='demo.topic',
                                         msg={'newer': 'packager'})
Exemplo n.º 14
0
def main(argv=sys.argv):
    """
    Search for overrides that are past their expiration date and mark them expired.

    Args:
        argv (list): The command line arguments. Defaults to sys.argv.
    """
    if len(argv) != 2:
        usage(argv)

    config_uri = argv[1]

    setup_logging()
    log = logging.getLogger(__name__)

    settings = get_appsettings(config_uri)
    initialize_db(settings)
    db = Session()

    setup_buildsystem(settings)

    try:
        now = datetime.utcnow()

        overrides = db.query(BuildrootOverride)
        overrides = overrides.filter(BuildrootOverride.expired_date.is_(None))
        overrides = overrides.filter(BuildrootOverride.expiration_date < now)

        count = overrides.count()

        if not count:
            log.info("No active buildroot override to expire")
            return

        log.info("Expiring %d buildroot overrides...", count)

        for override in overrides:
            log.debug(
                f"Expiring BRO for {override.build.nvr} because it's due to expire."
            )
            override.expire()
            db.add(override)
            log.info("Expired %s" % override.build.nvr)
        db.commit()
    except Exception as e:
        log.error(e)
        db.rollback()
        Session.remove()
        sys.exit(1)
Exemplo n.º 15
0
def check():
    """Check the enforced policies by Greenwave for each open update."""
    initialize_db(config.config)
    session = Session()

    updates = models.Update.query.filter(models.Update.status.in_(
        [models.UpdateStatus.pending, models.UpdateStatus.testing]))
    for update in updates:
        try:
            update.update_test_gating_status()
            session.commit()
        except Exception as e:
            # If there is a problem talking to Greenwave server, print the error.
            click.echo(str(e))
            session.rollback()
Exemplo n.º 16
0
def main():
    """
    Comment on updates that are eligible to be pushed to stable.

    Queries for updates in the testing state that have a NULL request, and run approve_update on
    them.
    """
    db = Session()
    try:
        testing = db.query(Update).filter_by(status=UpdateStatus.testing,
                                             request=None)
        for update in testing:
            approve_update(update, db)
            db.commit()
    except Exception:
        log.exception("There was an error approving testing updates.")
        db.rollback()
        Session.remove()
Exemplo n.º 17
0
def check():
    """Check the enforced policies by Greenwave for each open update."""
    initialize_db(config.config)
    session = Session()

    updates = models.Update.query.filter(models.Update.pushed == false())\
        .filter(models.Update.status.in_(
                [models.UpdateStatus.pending, models.UpdateStatus.testing]))
    for update in updates:
        # We retrieve updates going to testing (status=pending) and updates
        # (status=testing) going to stable.
        # If the update is pending, we want to know if it can go to testing
        decision_context = u'bodhi_update_push_testing'
        if update.status == models.UpdateStatus.testing:
            # Update is already in testing, let's ask if it can go to stable
            decision_context = u'bodhi_update_push_stable'

        data = {
            'product_version': update.product_version,
            'decision_context': decision_context,
            'subject': update.greenwave_subject
        }
        api_url = '{}/decision'.format(
            config.config.get('greenwave_api_url').rstrip('/'))

        try:
            decision = greenwave_api_post(api_url, data)
            if decision['policies_satisfied']:
                # If an unrestricted policy is applied and no tests are required
                # on this update, let's set the test gating as ignored in Bodhi.
                if decision['summary'] == 'no tests are required':
                    update.test_gating_status = models.TestGatingStatus.ignored
                else:
                    update.test_gating_status = models.TestGatingStatus.passed
            else:
                update.test_gating_status = models.TestGatingStatus.failed
            update.greenwave_summary_string = decision['summary']
            session.commit()
        except Exception as e:
            # If there is a problem talking to Greenwave server, print the error.
            click.echo(str(e))
            session.rollback()
Exemplo n.º 18
0
def approve_update(update: Update, db: Session):
    """Add a comment to an update if it is ready for stable.

    Check that the update is eligible to be pushed to stable but hasn't had comments from Bodhi to
    this effect. Add a comment stating that the update may now be pushed to stable.

    Args:
        update: an update in testing that may be ready for stable.
    """
    if not update.release.mandatory_days_in_testing and not update.autotime:
        # If this release does not have any testing requirements and is not autotime,
        # skip it
        log.info(
            f"{update.release.name} doesn't have mandatory days in testing")
        return
    # If this update was already commented, skip it
    if update.has_stable_comment:
        return
    # If updates have reached the testing threshold, say something! Keep in mind
    # that we don't care about karma here, because autokarma updates get their request set
    # to stable by the Update.comment() workflow when they hit the required threshold. Thus,
    # this function only needs to consider the time requirements because these updates have
    # not reached the karma threshold.
    if not update.meets_testing_requirements:
        return
    log.info(f'{update.alias} now meets testing requirements')
    # Only send email notification about the update reaching
    # testing approval on releases composed by bodhi
    update.comment(db,
                   str(config.get('testing_approval_msg')),
                   author='bodhi',
                   email_notification=update.release.composed_by_bodhi)
    notifications.publish(
        update_schemas.UpdateRequirementsMetStableV1.from_dict(
            dict(update=update)))
    if update.autotime and update.days_in_testing >= update.stable_days:
        log.info(f"Automatically marking {update.alias} as stable")
        # For now only rawhide update can be created using side tag
        # Do not add the release.pending_stable_tag if the update
        # was created from a side tag.
        if update.release.composed_by_bodhi:
            update.set_request(db=db,
                               action=UpdateRequest.stable,
                               username="******")
        # For updates that are not included in composes run by bodhi itself,
        # mark them as stable
        else:
            # Single and Multi build update
            conflicting_builds = update.find_conflicting_builds()
            if conflicting_builds:
                builds_str = str.join(", ", conflicting_builds)
                update.comment(
                    db, "This update cannot be pushed to stable. "
                    f"These builds {builds_str} have a more recent "
                    f"build in koji's {update.release.stable_tag} tag.",
                    author="bodhi")
                update.request = None
                if update.from_tag is not None:
                    update.status = UpdateStatus.pending
                    update.remove_tag(
                        update.release.get_testing_side_tag(update.from_tag))
                else:
                    update.status = UpdateStatus.obsolete
                    update.remove_tag(update.release.pending_testing_tag)
                    update.remove_tag(update.release.candidate_tag)
                db.commit()
                return
            update.add_tag(update.release.stable_tag)
            update.status = UpdateStatus.stable
            update.request = None
            update.pushed = True
            update.date_stable = update.date_pushed = func.current_timestamp()
            update.comment(
                db,
                "This update has been submitted for stable by bodhi",
                author=u'bodhi')
            update.modify_bugs()
            db.commit()
            # Multi build update
            if update.from_tag:
                # Merging the side tag should happen here
                pending_signing_tag = update.release.get_pending_signing_side_tag(
                    update.from_tag)
                testing_tag = update.release.get_testing_side_tag(
                    update.from_tag)
                update.remove_tag(pending_signing_tag)
                update.remove_tag(testing_tag)
                update.remove_tag(update.from_tag)
                koji = buildsys.get_session()
                koji.deleteTag(pending_signing_tag)
                koji.deleteTag(testing_tag)

            else:
                # Single build update
                update.remove_tag(update.release.pending_testing_tag)
                update.remove_tag(update.release.pending_stable_tag)
                update.remove_tag(update.release.pending_signing_tag)
                update.remove_tag(update.release.candidate_tag)
Exemplo n.º 19
0
def main(argv=sys.argv):
    """
    Comment on updates that are eligible to be pushed to stable.

    Queries for updates in the testing state that have a NULL request, looping over them looking for
    updates that are eligible to be pushed to stable but haven't had comments from Bodhi to this
    effect. For each such update it finds it will add a comment stating that the update may now be
    pushed to stable.

    This function is the entry point for the bodhi-approve-testing console script.

    Args:
        argv (list): A list of command line arguments. Defaults to sys.argv.
    """
    logging.basicConfig(level=logging.ERROR)

    if len(argv) != 2:
        usage(argv)

    settings = get_appsettings(argv[1])
    initialize_db(settings)
    db = Session()
    buildsys.setup_buildsystem(config)

    try:
        testing = db.query(Update).filter_by(status=UpdateStatus.testing,
                                             request=None)
        for update in testing:
            if not update.release.mandatory_days_in_testing and not update.autotime:
                # If this release does not have any testing requirements and is not autotime,
                # skip it
                print(
                    f"{update.release.name} doesn't have mandatory days in testing"
                )
                continue

            # If this update was already commented, skip it
            if update.has_stable_comment:
                continue

            # If updates have reached the testing threshold, say something! Keep in mind
            # that we don't care about karma here, because autokarma updates get their request set
            # to stable by the Update.comment() workflow when they hit the required threshold. Thus,
            # this function only needs to consider the time requirements because these updates have
            # not reached the karma threshold.
            if update.meets_testing_requirements:
                print(f'{update.alias} now meets testing requirements')
                # Only send email notification about the update reaching
                # testing approval on releases composed by bodhi
                update.comment(
                    db,
                    str(config.get('testing_approval_msg')),
                    author='bodhi',
                    email_notification=update.release.composed_by_bodhi)

                notifications.publish(
                    update_schemas.UpdateRequirementsMetStableV1.from_dict(
                        dict(update=update)))

                if update.autotime and update.days_in_testing >= update.stable_days:
                    print(f"Automatically marking {update.alias} as stable")
                    # For now only rawhide update can be created using side tag
                    # Do not add the release.pending_stable_tag if the update
                    # was created from a side tag.
                    if update.release.composed_by_bodhi:
                        update.set_request(db=db,
                                           action=UpdateRequest.stable,
                                           username="******")
                    # For updates that are not included in composes run by bodhi itself,
                    # mark them as stable
                    else:
                        # Single and Multi build update
                        conflicting_builds = update.find_conflicting_builds()
                        if conflicting_builds:
                            builds_str = str.join(", ", conflicting_builds)
                            update.comment(
                                db, "This update cannot be pushed to stable. "
                                f"These builds {builds_str} have a more recent "
                                f"build in koji's {update.release.stable_tag} tag.",
                                author="bodhi")
                            update.request = None
                            if update.from_tag is not None:
                                update.status = UpdateStatus.pending
                                update.remove_tag(
                                    update.release.get_testing_side_tag(
                                        update.from_tag))
                            else:
                                update.status = UpdateStatus.obsolete
                                update.remove_tag(
                                    update.release.pending_testing_tag)
                                update.remove_tag(update.release.candidate_tag)
                            db.commit()
                            continue

                        update.add_tag(update.release.stable_tag)
                        update.status = UpdateStatus.stable
                        update.request = None
                        update.pushed = True
                        update.date_stable = update.date_pushed = func.current_timestamp(
                        )
                        update.comment(
                            db,
                            "This update has been submitted for stable by bodhi",
                            author=u'bodhi')

                        # Multi build update
                        if update.from_tag:
                            # Merging the side tag should happen here
                            pending_signing_tag = update.release.get_pending_signing_side_tag(
                                update.from_tag)
                            testing_tag = update.release.get_testing_side_tag(
                                update.from_tag)

                            update.remove_tag(pending_signing_tag)
                            update.remove_tag(testing_tag)
                            update.remove_tag(update.from_tag)

                            koji = buildsys.get_session()
                            koji.deleteTag(pending_signing_tag)
                            koji.deleteTag(testing_tag)

                            # Removes the tag and the build target from koji.
                            koji.removeSideTag(update.from_tag)
                        else:
                            # Single build update
                            update.remove_tag(
                                update.release.pending_testing_tag)
                            update.remove_tag(
                                update.release.pending_stable_tag)
                            update.remove_tag(
                                update.release.pending_signing_tag)
                            update.remove_tag(update.release.candidate_tag)

                db.commit()

    except Exception as e:
        print(str(e))
        db.rollback()
        Session.remove()
        sys.exit(1)
Exemplo n.º 20
0
def main(argv=sys.argv):
    """
    Comment on updates that are eligible to be pushed to stable.

    Queries for updates in the testing state that have a NULL request, looping over them looking for
    updates that are eligible to be pushed to stable but haven't had comments from Bodhi to this
    effect. For each such update it finds it will add a comment stating that the update may now be
    pushed to stable.

    This function is the entry point for the bodhi-approve-testing console script.

    Args:
        argv (list): A list of command line arguments. Defaults to sys.argv.
    """
    logging.basicConfig(level=logging.ERROR)

    if len(argv) != 2:
        usage(argv)

    settings = get_appsettings(argv[1])
    initialize_db(settings)
    db = Session()

    try:
        testing = db.query(Update).filter_by(status=UpdateStatus.testing,
                                             request=None)
        for update in testing:
            if not update.release.mandatory_days_in_testing and not update.autotime:
                # If this release does not have any testing requirements and is not autotime,
                # skip it
                print(
                    f"{update.release.name} doesn't have mandatory days in testing"
                )
                continue

            # If this update was already commented, skip it
            if update.has_stable_comment:
                continue

            # If updates have reached the testing threshold, say something! Keep in mind
            # that we don't care about karma here, because autokarma updates get their request set
            # to stable by the Update.comment() workflow when they hit the required threshold. Thus,
            # this function only needs to consider the time requirements because these updates have
            # not reached the karma threshold.
            if update.meets_testing_requirements:
                print(f'{update.alias} now meets testing requirements')
                update.comment(db,
                               str(config.get('testing_approval_msg')),
                               author='bodhi')

                notifications.publish(
                    update_schemas.UpdateRequirementsMetStableV1.from_dict(
                        dict(update=update)))

                if update.autotime and update.days_in_testing >= update.stable_days:
                    print(f"Automatically marking {update.alias} as stable")
                    update.set_request(db=db,
                                       action=UpdateRequest.stable,
                                       username="******")

                db.commit()

    except Exception as e:
        print(str(e))
        db.rollback()
        Session.remove()
        sys.exit(1)
Exemplo n.º 21
0
def main(argv=sys.argv):
    """
    Comment on updates that are eligible to be pushed to stable.

    Queries for updates in the testing state that have a NULL request, looping over them looking for
    updates that are eligible to be pushed to stable but haven't had comments from Bodhi to this
    effect. For each such update it finds it will add a comment stating that the update may now be
    pushed to stable.

    This function is the entry point for the bodhi-approve-testing console script.

    Args:
        argv (list): A list of command line arguments. Defaults to sys.argv.
    """
    if len(argv) != 2:
        usage(argv)

    settings = get_appsettings(argv[1])
    initialize_db(settings)
    db = Session()

    try:
        testing = db.query(Update).filter_by(status=UpdateStatus.testing,
                                             request=None)
        for update in testing:
            # If this release does not have any testing requirements, skip it
            if not update.release.mandatory_days_in_testing:
                print('%s doesn\'t have mandatory days in testing' %
                      update.release.name)
                continue

            # If this has already met testing requirements, skip it
            if update.met_testing_requirements:
                continue

            # Approval message when testing based on karma threshold
            if update.stable_karma not in (0, None) and update.karma >= update.stable_karma \
                    and not update.autokarma and update.meets_testing_requirements:
                print('%s now reaches stable karma threshold' % update.title)
                text = config.get('testing_approval_msg_based_on_karma')
                update.comment(db, text, author=u'bodhi')
                continue

            # If autokarma updates have reached the testing threshold, say something! Keep in mind
            # that we don't care about karma here, because autokarma updates get their request set
            # to stable by the Update.comment() workflow when they hit the required threshold. Thus,
            # this function only needs to consider the time requirements because these updates have
            # not reached the karma threshold.
            if update.meets_testing_requirements:
                print('%s now meets testing requirements' % update.title)
                text = six.text_type(
                    config.get('testing_approval_msg') %
                    update.mandatory_days_in_testing)
                update.comment(db, text, author=u'bodhi')

                notifications.publish(topic='update.requirements_met.stable',
                                      msg=dict(update=update))

        db.commit()
    except Exception as e:
        print(str(e))
        db.rollback()
        Session.remove()
        sys.exit(1)