예제 #1
0
    def command_FORCE(self, args, tquery=None, partial=None, **kwargs):
        """force a build"""

        try:
            forceschedulers = yield self.master.data.get(('forceschedulers',))
        except AttributeError:
            forceschedulers = None
        else:
            forceschedulers = dict((s['name'], s) for s in forceschedulers)

        if not forceschedulers:
            raise UsageError("no force schedulers configured for use by /force")

        argv = self.splitArgs(args)

        try:
            sched = argv[0]
        except IndexError:
            if len(forceschedulers) == 1:
                sched = next(iter(forceschedulers))
            else:
                keyboard = [
                    [self.query_button(s['label'], '/force {}'.format(s['name']))]
                    for s in forceschedulers.values()
                ]
                self.send("Which force scheduler do you want to activate?",
                          reply_markup={'inline_keyboard': keyboard})
                return
        else:
            if sched in forceschedulers:
                del argv[0]
            elif len(forceschedulers) == 1:
                sched = next(iter(forceschedulers))
            else:
                raise UsageError("Try '/force' and follow the instructions"
                                 " (no force scheduler {})".format(sched))
        scheduler = forceschedulers[sched]

        try:
            task = argv.pop(0)
        except IndexError:
            task = 'config'

        if tquery and task != 'config':
            self.bot.edit_keyboard(self.chat_id, tquery['message']['message_id'])

        if not argv:
            keyboard = [
                [self.query_button(b, '/force {} {} {}'.format(sched, task, b))]
                for b in scheduler['builder_names']
            ]
            self.send("Which builder do you want to start?",
                      reply_markup={'inline_keyboard': keyboard})
            return

        if task == 'ask':
            try:
                what = argv.pop(0)
            except IndexError:
                raise UsageError("Try '/force' and follow the instructions")
        else:
            what = None  # silence PyCharm warnings

        bldr = argv.pop(0)
        if bldr not in scheduler['builder_names']:
            raise UsageError(("Try '/force' and follow the instructions "
                              "(`{}` not configured for _{}_ scheduler)"
                              ).format(bldr, scheduler['label']))

        try:
            params = dict(arg.split('=', 1) for arg in argv)
        except ValueError as err:
            raise UsageError("Try '/force' and follow the instructions ({})".format(err))

        all_fields = list(collect_fields(scheduler['all_fields']))
        required_params = [f['fullName'] for f in all_fields
                           if f['required'] and f['fullName'] not in ('username', 'owner')]
        missing_params = [p for p in required_params if p not in params]

        if task == 'build':
            # TODO This should probably be moved to the upper class,
            # however, it will change the force command totally

            try:
                if missing_params:
                    # raise UsageError
                    task = 'config'
                else:
                    params.update(dict(
                        (f['fullName'], f['default']) for f in all_fields
                        if f['type'] == 'fixed' and f['fullName'] not in ('username', 'owner')
                    ))

                    builder = yield self.bot.getBuilder(buildername=bldr)
                    for scheduler in self.master.allSchedulers():
                        if scheduler.name == sched and isinstance(scheduler, ForceScheduler):
                            break
                    else:
                        raise ValueError("There is no force scheduler '{}'".format(sched))
                    try:
                        yield scheduler.force(builderid=builder['builderid'],
                                              owner=self.describeUser(),
                                              **params)
                    except CollectedValidationError as err:
                        raise ValueError(err.errors)
                    else:
                        self.send("Force build successfully requested.")
                    return

            except (IndexError, ValueError) as err:
                raise UsageError("Try '/force' and follow the instructions ({})".format(err))

        if task == 'config':

            msg = "{}, you are about to start a new build on `{}`!"\
                .format(self.user_full_name, bldr)

            keyboard = []
            args = ' '.join(shlex.quote("{}={}".format(*p)) for p in params.items())

            fields = [f for f in all_fields if f['type'] != 'fixed'
                      and f['fullName'] not in ('username', 'owner')]

            if fields:
                msg += "\n\nThe current build parameters are:"
                for field in fields:
                    if field['type'] == 'nested':
                        msg += "\n{}".format(field['label'])
                    else:
                        field_name = field['fullName']
                        value = params.get(field_name, field['default']).strip()
                        msg += "\n    {} `{}`".format(field['label'], value)
                        if value:
                            key = "Change "
                        else:
                            key = "Set "
                        key += field_name.replace('_', ' ').title()
                        if field_name in missing_params:
                            key = "⚠️ " + key
                            msg += " ⚠️"
                        keyboard.append(
                            [self.query_button(key, '/force {} ask {} {} {}'
                                               .format(sched, field_name, bldr, args))]
                        )

            msg += "\n\nWhat do you want to do?"
            if missing_params:
                msg += " You must set values for all parameters marked with ⚠️"

            if not missing_params:
                keyboard.append(
                    [self.query_button("🚀 Start Build", '/force {} build {} {}'
                                       .format(sched, bldr, args))],
                )

            self.send(msg, reply_markup={'inline_keyboard': keyboard})

        elif task == 'ask':
            prompt = "enter the new value for the " + what.replace('_', ' ').lower()
            args = ' '.join(shlex.quote("{}={}".format(*p)) for p in params.items()
                            if p[0] != what)
            self.template = '/force {} config {} {} {}={{}}'.format(sched, bldr, args, what)
            self.ask_for_reply(prompt, '')

        else:
            raise UsageError("Try '/force' and follow the instructions")
예제 #2
0
    def command_LIST(self, args, **kwargs):
        args = self.splitArgs(args)
        if not args:
            keyboard = [
                [self.query_button("👷️ Builders", '/list builders'),
                 self.query_button("👷️ (including old ones)", '/list all builders')],
                [self.query_button("⚙ Workers", '/list workers'),
                 self.query_button("⚙ (including old ones)", '/list all workers')],
                [self.query_button("📄 Changes (last 10)", '/list changes')],
            ]
            self.send("What do you want to list?",
                      reply_markup={'inline_keyboard': keyboard})
            return

        all = False
        num = 10
        try:
            num = int(args[0])
            del args[0]
        except ValueError:
            if args[0] == 'all':
                all = True
                del args[0]
        except IndexError:
            pass

        if not args:
            raise UsageError("Try '" + self.bot.commandPrefix +
                             "list [all|N] builders|workers|changes'.")

        if args[0] == 'builders':
            bdicts = yield self.bot.getAllBuilders()
            online_builderids = yield self.bot.getOnlineBuilders()

            response = ["I found the following **builders**:"]
            for bdict in bdicts:
                if bdict['builderid'] in online_builderids:
                    response.append("`{}`".format(bdict['name']))
                elif all:
                    response.append("`{}` ❌".format(bdict['name']))
            self.send('\n'.join(response))

        elif args[0] == 'workers':
            workers = yield self.master.data.get(('workers',))

            response = ["I found the following **workers**:"]
            for worker in workers:
                if worker['configured_on']:
                    response.append("`{}`".format(worker['name']))
                    if not worker['connected_to']:
                        response[-1] += " ⚠️"
                elif all:
                    response.append("`{}` ❌".format(worker['name']))
            self.send('\n'.join(response))

        elif args[0] == 'changes':

            wait_message = yield self.send("⏳ Getting your changes...")

            if all:
                changes = yield self.master.data.get(('changes',))
                self.bot.delete_message(self.channel.id, wait_message['message_id'])
                num = len(changes)
                if num > 50:
                    keyboard = [
                        [self.query_button("‼ Yes, flood me with all of them!",
                                           '/list {} changes'.format(num))],
                        [self.query_button("✅ No, just show last 50", '/list 50 changes')]
                    ]
                    self.send("I found {} changes. Do you really want me "
                              "to list them all?".format(num),
                              reply_markup={'inline_keyboard': keyboard})
                    return

            else:
                changes = yield self.master.data.get(('changes',), order=['-changeid'], limit=num)
                self.bot.delete_message(self.channel.id, wait_message['message_id'])

            response = ["I found the following recent **changes**:\n"]

            for change in reversed(changes):
                change['comment'] = change['comments'].split('\n')[0]
                change['date'] = epoch2datetime(change['when_timestamp']).strftime('%Y-%m-%d %H:%M')
                response.append(
                    "[{comment}]({revlink})\n"
                    "_Author_: {author}\n"
                    "_Date_: {date}\n"
                    "_Repository_: {repository}\n"
                    "_Branch_: {branch}\n"
                    "_Revision_: {revision}\n".format(**change))
            self.send('\n'.join(response))