Exemple #1
0
    def test_process_remove_platforms(self):
        BuildConfig(self.env, name='foo', label='Foo', path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []
        def redirect(url):
            redirected_to.append(url)
            raise RequestDone
        req = Mock(method='POST', perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'), redirect=redirect,
                   authname='joe', chrome={'warnings': [], 'notices': []},
                   href=Href('/'),
                   args={'remove': '', 'sel': str(platform.id)})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs', 'foo')
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEquals(['Target Platform(s) Removed.'],
                               req.chrome['notices'])
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(0, len(platforms))
Exemple #2
0
    def test_process_update_platform_cancel(self):
        BuildConfig(self.env, name='foo', label='Foo', path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []
        def redirect(url):
            redirected_to.append(url)
            raise RequestDone
        req = Mock(method='POST', perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'), redirect=redirect,
                   authname='joe',
                   args={'cancel': '', 'edit': '', 'name': 'Changed',
                         'property_0': 'family', 'pattern_0': 'posix'})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs',
                                           'foo/%d' % platform.id)
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(1, len(platforms))
            self.assertEqual('any', platforms[0].name)
            self.assertEqual([], platforms[0].rules)
Exemple #3
0
 def test_select(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.executemany("INSERT INTO bitten_platform (config,name) "
                        "VALUES (%s,%s)", [('test', 'Windows'),
                        ('test', 'Mac OS X')])
     platforms = list(TargetPlatform.select(self.env, config='test'))
     self.assertEqual(2, len(platforms))
Exemple #4
0
    def test_process_remove_platforms(self):
        BuildConfig(self.env,
                    name='foo',
                    label='Foo',
                    path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []

        def redirect(url):
            redirected_to.append(url)
            raise RequestDone

        req = Mock(method='POST',
                   perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'),
                   redirect=redirect,
                   authname='joe',
                   chrome={
                       'warnings': [],
                       'notices': []
                   },
                   href=Href('/'),
                   args={
                       'remove': '',
                       'sel': str(platform.id)
                   })

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs', 'foo')
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEquals(['Target Platform(s) Removed.'],
                              req.chrome['notices'])
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(0, len(platforms))
Exemple #5
0
    def match_slave(self, name, properties):
        """Match a build slave against available target platforms.
        
        :param name: the name of the slave
        :type name: `basestring`
        :param properties: the slave configuration
        :type properties: `dict`
        :return: the list of platforms the slave matched
        """
        platforms = []

        for config in BuildConfig.select(self.env):
            for platform in TargetPlatform.select(self.env,
                                                  config=config.name):
                match = True
                for propname, pattern in ifilter(None, platform.rules):
                    try:
                        propvalue = properties.get(propname)
                        if not propvalue or not re.match(
                                pattern, propvalue, re.I):
                            match = False
                            break
                    except re.error:
                        self.log.error(
                            'Invalid platform matching pattern "%s"',
                            pattern,
                            exc_info=True)
                        match = False
                        break
                if match:
                    self.log.debug(
                        'Slave %r matched target platform %r of '
                        'build configuration %r', name, platform.name,
                        config.name)
                    platforms.append(platform)

        if not platforms:
            self.log.warning('Slave %r matched none of the target platforms',
                             name)

        return platforms
Exemple #6
0
    def test_process_update_platform_cancel(self):
        BuildConfig(self.env,
                    name='foo',
                    label='Foo',
                    path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []

        def redirect(url):
            redirected_to.append(url)
            raise RequestDone

        req = Mock(method='POST',
                   perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'),
                   redirect=redirect,
                   authname='joe',
                   args={
                       'cancel': '',
                       'edit': '',
                       'name': 'Changed',
                       'property_0': 'family',
                       'pattern_0': 'posix'
                   })

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs',
                                        'foo/%d' % platform.id)
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(1, len(platforms))
            self.assertEqual('any', platforms[0].name)
            self.assertEqual([], platforms[0].rules)
Exemple #7
0
    def match_slave(self, name, properties):
        """Match a build slave against available target platforms.
        
        :param name: the name of the slave
        :type name: `basestring`
        :param properties: the slave configuration
        :type properties: `dict`
        :return: the list of platforms the slave matched
        """
        platforms = []

        for config in BuildConfig.select(self.env):
            for platform in TargetPlatform.select(self.env, config=config.name):
                match = True
                for propname, pattern in ifilter(None, platform.rules):
                    try:
                        propvalue = properties.get(propname)
                        if not propvalue or not re.match(pattern,
                                                         propvalue, re.I):
                            match = False
                            break
                    except re.error:
                        self.log.error('Invalid platform matching pattern "%s"',
                                       pattern, exc_info=True)
                        match = False
                        break
                if match:
                    self.log.debug('Slave %r matched target platform %r of '
                                   'build configuration %r', name,
                                   platform.name, config.name)
                    platforms.append(platform)

        if not platforms:
            self.log.warning('Slave %r matched none of the target platforms',
                             name)

        return platforms
Exemple #8
0
    def render_admin_panel(self, req, cat, page, path_info):
        data = {}

        # Analyze url
        try:
            config_name, platform_id = path_info.split('/', 1)
        except:
            config_name = path_info
            platform_id = None

        if config_name: # Existing build config
            if platform_id or (
                    # Editing or creating one of the config's target platforms
                    req.method == 'POST' and 'new' in req.args):

                if platform_id: # Editing target platform
                    platform_id = int(platform_id)
                    platform = TargetPlatform.fetch(self.env, platform_id)

                    if req.method == 'POST':
                        if 'cancel' in req.args or \
                                self._update_platform(req, platform):
                            req.redirect(req.abs_href.admin(cat, page,
                                                            config_name))
                else: # creating target platform
                    if req.method == 'POST':
                        if 'add' in req.args:
                            self._create_platform(req, config_name)
                            req.redirect(req.abs_href.admin(cat, page,
                                                            config_name))
                        elif 'cancel' in req.args:
                            req.redirect(req.abs_href.admin(cat, page,
                                                            config_name))

                    platform = TargetPlatform(self.env, config=config_name)

                # Set up template variables
                data['platform'] = {
                    'id': platform.id, 'name': platform.name,
                    'exists': platform.exists,
                    'rules': [
                        {'property': propname, 'pattern': pattern}
                        for propname, pattern in platform.rules
                    ] or [('', '')]
                }

            else: # Editing existing build config itself
                config = BuildConfig.fetch(self.env, config_name)
                platforms = list(TargetPlatform.select(self.env,
                                                       config=config.name))

                if req.method == 'POST':
                    if 'add' in req.args: # Add target platform
                        platform = self._create_platform(req, config)
                        req.redirect(req.abs_href.admin(cat, page, config.name))

                    elif 'remove' in req.args: # Remove selected platforms
                        self._remove_platforms(req)
                        req.redirect(req.abs_href.admin(cat, page, config.name))

                    elif 'save' in req.args: # Save this build config
                        self._update_config(req, config)

                    req.redirect(req.abs_href.admin(cat, page))

                # Prepare template variables
                data['config'] = {
                    'name': config.name, 'label': config.label or config.name,
                    'active': config.active, 'path': config.path,
                    'min_rev': config.min_rev, 'max_rev': config.max_rev,
                    'description': config.description,
                    'recipe': config.recipe,
                    'platforms': [{
                        'name': platform.name,
                        'id': platform.id,
                        'href': req.href.admin('bitten', 'configs', config.name,
                                               platform.id),
                        'rules': [{'property': propname, 'pattern': pattern}
                                   for propname, pattern in platform.rules]
                    } for platform in platforms]
                }

        else: # At the top level build config list
            if req.method == 'POST':
                if 'add' in req.args: # Add build config
                    config = self._create_config(req)
                    req.redirect(req.abs_href.admin(cat, page, config.name))

                elif 'remove' in req.args: # Remove selected build configs
                    self._remove_configs(req)

                elif 'apply' in req.args: # Update active state of configs
                    self._activate_configs(req)
                req.redirect(req.abs_href.admin(cat, page))

            # Prepare template variables
            configs = []
            for config in BuildConfig.select(self.env, include_inactive=True):
                configs.append({
                    'name': config.name, 'label': config.label or config.name,
                    'active': config.active, 'path': config.path,
                    'min_rev': config.min_rev, 'max_rev': config.max_rev,
                    'href': req.href.admin('bitten', 'configs', config.name),
                })
            data['configs'] = configs

        add_stylesheet(req, 'bitten/admin.css')
        add_script(req, 'common/js/suggest.js')
        return 'bitten_admin_configs.html', data
Exemple #9
0
    def _render_config(self, req, config_name):
        db = self.env.get_db_cnx()

        config = BuildConfig.fetch(self.env, config_name, db=db)
        if not config:
            raise HTTPNotFound("Build configuration '%s' does not exist." \
                                % config_name)

        repos = self.env.get_repository(req.authname)
        repos.authz.assert_permission(config.branch)

        data = {'title': 'Build Configuration "%s"' \
                          % config.label or config.name,
                'page_mode': 'view_config'}
        add_link(req, 'up', req.href.build(), 'Build Status')
        description = config.description
        if description:
            description = wiki_to_html(description, self.env, req)

        pending_builds = list(
            Build.select(self.env, config=config.name, status=Build.PENDING))
        inprogress_builds = list(
            Build.select(self.env,
                         config=config.name,
                         status=Build.IN_PROGRESS))

        rev = ''

        for b in repos.git.get_branches():
            if b[0] == config.branch:
                rev = b[1]
                break

        data['config'] = {
            'name': config.name,
            'label': config.label,
            'branch': config.branch,
            'active': config.active,
            'description': description,
            'browser_href': req.href.browser(rev=rev),
            'builds_pending': len(pending_builds),
            'builds_inprogress': len(inprogress_builds)
        }

        context = Context.from_request(req, config.resource)
        data['context'] = context
        data['config']['attachments'] = AttachmentModule(
            self.env).attachment_data(context)

        platforms = list(
            TargetPlatform.select(self.env, config=config_name, db=db))
        data['config']['platforms'] = [{
            'name':
            platform.name,
            'id':
            platform.id,
            'builds_pending':
            len(
                list(
                    Build.select(self.env,
                                 config=config.name,
                                 status=Build.PENDING,
                                 platform=platform.id))),
            'builds_inprogress':
            len(
                list(
                    Build.select(self.env,
                                 config=config.name,
                                 status=Build.IN_PROGRESS,
                                 platform=platform.id)))
        } for platform in platforms]

        has_reports = False
        for report in Report.select(self.env, config=config.name, db=db):
            has_reports = True
            break

        if has_reports:
            chart_generators = []
            for generator in ReportChartController(self.env).generators:
                for category in generator.get_supported_categories():
                    chart_generators.append({
                        'href':
                        req.href.build(config.name, 'chart/' + category)
                    })
            data['config']['charts'] = chart_generators
            charts_license = self.config.get('bitten', 'charts_license')
            if charts_license:
                data['config']['charts_license'] = charts_license

        page = max(1, int(req.args.get('page', 1)))
        more = False
        data['page_number'] = page

        repos = self.env.get_repository(req.authname)

        builds_per_page = 12 * len(platforms)
        idx = 0
        builds = {}
        for platform, rev, build in collect_changes(repos, config):
            if idx >= page * builds_per_page:
                more = True
                break
            elif idx >= (page - 1) * builds_per_page:
                builds.setdefault(rev, {})
                builds[rev].setdefault('href', req.href.changeset(rev))
                if build and build.status != Build.PENDING:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['steps'] = []
                    for step in BuildStep.select(self.env,
                                                 build=build.id,
                                                 db=db):
                        build_data['steps'].append({
                            'name': step.name,
                            'description': step.description,
                            'duration': to_datetime(step.stopped, utc) - \
                                        to_datetime(step.started, utc),
                            'failed': not step.successful,
                            'errors': step.errors,
                            'href': build_data['href'] + '#step_' + step.name
                        })
                    builds[rev][platform.id] = build_data
            idx += 1
        data['config']['builds'] = builds

        if page > 1:
            if page == 2:
                prev_href = req.href.build(config.name)
            else:
                prev_href = req.href.build(config.name, page=page - 1)
            add_link(req, 'prev', prev_href, 'Previous Page')
        if more:
            next_href = req.href.build(config.name, page=page + 1)
            add_link(req, 'next', next_href, 'Next Page')
        prevnext_nav(req, 'Page')
        return data
Exemple #10
0
    def _render_overview(self, req):
        data = {'title': 'Build Status'}
        show_all = False
        if req.args.get('show') == 'all':
            show_all = True
        data['show_all'] = show_all

        repos = self.env.get_repository(req.authname)

        configs = []
        for config in BuildConfig.select(self.env, include_inactive=show_all):
            if not repos.authz.has_permission(config.branch):
                continue

            description = config.description
            if description:
                description = wiki_to_html(description, self.env, req)

            platforms_data = []
            for platform in TargetPlatform.select(self.env,
                                                  config=config.name):
                pd = {
                    'name':
                    platform.name,
                    'id':
                    platform.id,
                    'builds_pending':
                    len(
                        list(
                            Build.select(self.env,
                                         config=config.name,
                                         status=Build.PENDING,
                                         platform=platform.id))),
                    'builds_inprogress':
                    len(
                        list(
                            Build.select(self.env,
                                         config=config.name,
                                         status=Build.IN_PROGRESS,
                                         platform=platform.id)))
                }
                platforms_data.append(pd)

            config_data = {
                'name':
                config.name,
                'label':
                config.label or config.name,
                'active':
                config.active,
                'branch':
                config.branch,
                'description':
                description,
                'builds_pending':
                len(
                    list(
                        Build.select(self.env,
                                     config=config.name,
                                     status=Build.PENDING))),
                'builds_inprogress':
                len(
                    list(
                        Build.select(self.env,
                                     config=config.name,
                                     status=Build.IN_PROGRESS))),
                'href':
                req.href.build(config.name),
                'builds': [],
                'platforms':
                platforms_data
            }
            configs.append(config_data)
            if not config.active:
                continue

            prev_rev = None
            for platform, rev, build in collect_changes(repos, config):
                if rev != prev_rev:
                    if prev_rev is None:
                        chgset = repos.get_changeset(rev)
                        config_data['youngest_rev'] = {
                            'id':
                            rev,
                            'href':
                            req.href.changeset(rev),
                            'author':
                            chgset.author or 'anonymous',
                            'date':
                            format_datetime(chgset.date),
                            'message':
                            wiki_to_oneliner(shorten_line(chgset.message),
                                             self.env,
                                             req=req)
                        }
                    else:
                        break
                    prev_rev = rev
                if build:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['platform'] = platform.name
                    config_data['builds'].append(build_data)
                else:
                    config_data['builds'].append({
                        'platform': platform.name,
                        'status': 'pending'
                    })

        data['configs'] = configs
        data['page_mode'] = 'overview'

        in_progress_builds = Build.select(self.env, status=Build.IN_PROGRESS)
        pending_builds = Build.select(self.env, status=Build.PENDING)

        data['builds_pending'] = len(list(pending_builds))
        data['builds_inprogress'] = len(list(in_progress_builds))

        add_link(req, 'views', req.href.build(view='inprogress'),
                 'In Progress Builds')
        add_ctxtnav(req, 'In Progress Builds',
                    req.href.build(view='inprogress'))
        return data
Exemple #11
0
    def _render_overview(self, req):
        data = {'title': 'Build Status'}
        show_all = False
        if req.args.get('show') == 'all':
            show_all = True
        data['show_all'] = show_all

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'

        configs = []
        for config in BuildConfig.select(self.env, include_inactive=show_all):
            rev = config.max_rev or repos.youngest_rev
            try:
                if not _has_permission(req.perm, repos, config.path, rev=rev):
                    continue
            except NoSuchNode:
                add_warning(req, "Configuration '%s' points to non-existing "
                        "path '/%s' at revision '%s'. Configuration skipped." \
                                    % (config.name, config.path, rev))
                continue

            description = config.description
            if description:
                description = wiki_to_html(description, self.env, req)

            platforms_data = []
            for platform in TargetPlatform.select(self.env, config=config.name):
                pd = { 'name': platform.name,
                       'id': platform.id,
                       'builds_pending': len(list(Build.select(self.env,
                                config=config.name, status=Build.PENDING,
                                platform=platform.id))),
                       'builds_inprogress': len(list(Build.select(self.env,
                                config=config.name, status=Build.IN_PROGRESS,
                                platform=platform.id)))
                }
                platforms_data.append(pd)

            config_data = {
                'name': config.name, 'label': config.label or config.name,
                'active': config.active, 'path': config.path,
                'description': description,
                'builds_pending' : len(list(Build.select(self.env,
                                                config=config.name,
                                                status=Build.PENDING))),
                'builds_inprogress' : len(list(Build.select(self.env,
                                                config=config.name,
                                                status=Build.IN_PROGRESS))),
                'href': req.href.build(config.name),
                'builds': [],
                'platforms': platforms_data
            }
            configs.append(config_data)
            if not config.active:
                continue

            prev_rev = None
            for platform, rev, build in collect_changes(repos, config):
                if rev != prev_rev:
                    if prev_rev is None:
                        chgset = repos.get_changeset(rev)
                        config_data['youngest_rev'] = {
                            'id': rev, 'href': req.href.changeset(rev),
                            'display_rev': repos.normalize_rev(rev),
                            'author': chgset.author or 'anonymous',
                            'date': format_datetime(chgset.date),
                            'message': wiki_to_oneliner(
                                shorten_line(chgset.message), self.env, req=req)
                        }
                    else:
                        break
                    prev_rev = rev
                if build:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['platform'] = platform.name
                    config_data['builds'].append(build_data)
                else:
                    config_data['builds'].append({
                        'platform': platform.name, 'status': 'pending'
                    })

        data['configs'] = sorted(configs, key=lambda x:x['label'].lower())
        data['page_mode'] = 'overview'

        in_progress_builds = Build.select(self.env, status=Build.IN_PROGRESS)
        pending_builds = Build.select(self.env, status=Build.PENDING)

        data['builds_pending'] = len(list(pending_builds))
        data['builds_inprogress'] = len(list(in_progress_builds))

        add_link(req, 'views', req.href.build(view='inprogress'),
                 'In Progress Builds')
        add_ctxtnav(req, 'In Progress Builds',
                    req.href.build(view='inprogress'))
        return data
Exemple #12
0
    def _render_config(self, req, config_name):
        db = self.env.get_db_cnx()

        config = BuildConfig.fetch(self.env, config_name, db=db)
        if not config:
            raise HTTPNotFound("Build configuration '%s' does not exist." \
                                % config_name)

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'
        rev = config.max_rev or repos.youngest_rev
        try:
            _has_permission(req.perm,
                            repos,
                            config.path,
                            rev=rev,
                            raise_error=True)
        except NoSuchNode:
            raise TracError("Permission checking against repository path %s "
                            "at revision %s failed." % (config.path, rev))

        data = {'title': 'Build Configuration "%s"' \
                          % config.label or config.name,
                'page_mode': 'view_config'}
        add_link(req, 'up', req.href.build(), 'Build Status')
        description = config.description
        if description:
            description = wiki_to_html(description, self.env, req)

        pending_builds = list(
            Build.select(self.env, config=config.name, status=Build.PENDING))
        inprogress_builds = list(
            Build.select(self.env,
                         config=config.name,
                         status=Build.IN_PROGRESS))

        data['config'] = {
            'name': config.name,
            'label': config.label,
            'path': config.path,
            'min_rev': config.min_rev,
            'min_rev_href': req.href.changeset(config.min_rev),
            'max_rev': config.max_rev,
            'max_rev_href': req.href.changeset(config.max_rev),
            'active': config.active,
            'description': description,
            'browser_href': req.href.browser(config.path),
            'builds_pending': len(pending_builds),
            'builds_inprogress': len(inprogress_builds)
        }

        context = Context.from_request(req, config.resource)
        data['context'] = context
        data['config']['attachments'] = AttachmentModule(
            self.env).attachment_data(context)

        platforms = list(
            TargetPlatform.select(self.env, config=config_name, db=db))
        data['config']['platforms'] = [{
            'name':
            platform.name,
            'id':
            platform.id,
            'builds_pending':
            len(
                list(
                    Build.select(self.env,
                                 config=config.name,
                                 status=Build.PENDING,
                                 platform=platform.id))),
            'builds_inprogress':
            len(
                list(
                    Build.select(self.env,
                                 config=config.name,
                                 status=Build.IN_PROGRESS,
                                 platform=platform.id)))
        } for platform in platforms]

        has_reports = False
        for report in Report.select(self.env, config=config.name, db=db):
            has_reports = True
            break

        if has_reports:
            chart_generators = []
            report_categories = list(
                self._report_categories_for_config(config))
            for generator in ReportChartController(self.env).generators:
                for category in generator.get_supported_categories():
                    if category in report_categories:
                        chart_generators.append({
                            'href':
                            req.href.build(config.name, 'chart/' + category),
                            'category':
                            category,
                            'style':
                            self.config.get('bitten', 'chart_style'),
                        })
            data['config']['charts'] = chart_generators

        page = max(1, int(req.args.get('page', 1)))
        more = False
        data['page_number'] = page

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'

        builds_per_page = 12 * len(platforms)
        idx = 0
        builds = {}
        revisions = []
        for platform, rev, build in collect_changes(repos, config):
            if idx >= page * builds_per_page:
                more = True
                break
            elif idx >= (page - 1) * builds_per_page:
                if rev not in builds:
                    revisions.append(rev)
                builds.setdefault(rev, {})
                builds[rev].setdefault('href', req.href.changeset(rev))
                builds[rev].setdefault('display_rev', repos.normalize_rev(rev))
                if build and build.status != Build.PENDING:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['steps'] = []
                    for step in BuildStep.select(self.env,
                                                 build=build.id,
                                                 db=db):
                        build_data['steps'].append({
                            'name': step.name,
                            'description': step.description,
                            'duration': to_datetime(step.stopped or int(time.time()), utc) - \
                                        to_datetime(step.started, utc),
                            'status': _step_status_label[step.status],
                            'cls': _step_status_label[step.status].replace(' ', '-'),

                            'errors': step.errors,
                            'href': build_data['href'] + '#step_' + step.name
                        })
                    builds[rev][platform.id] = build_data
            idx += 1
        data['config']['builds'] = builds
        data['config']['revisions'] = revisions

        if page > 1:
            if page == 2:
                prev_href = req.href.build(config.name)
            else:
                prev_href = req.href.build(config.name, page=page - 1)
            add_link(req, 'prev', prev_href, 'Previous Page')
        if more:
            next_href = req.href.build(config.name, page=page + 1)
            add_link(req, 'next', next_href, 'Next Page')
        if arity(prevnext_nav) == 4:  # Trac 0.12 compat, see #450
            prevnext_nav(req, 'Previous Page', 'Next Page')
        else:
            prevnext_nav(req, 'Page')
        return data
Exemple #13
0
    def _render_config(self, req, config_name):
        db = self.env.get_db_cnx()

        config = BuildConfig.fetch(self.env, config_name, db=db)

        repos = self.env.get_repository(req.authname)
        if hasattr(repos, 'sync'):
            repos.sync()
        repos.authz.assert_permission(config.path)

        data = {'title': 'Build Configuration "%s"' \
                          % config.label or config.name,
                'page_mode': 'view_config'}
        add_link(req, 'up', req.href.build(), 'Build Status')
        description = config.description
        if description:
            description = wiki_to_html(description, self.env, req)

        pending_builds = list(Build.select(self.env, config=config.name, status=Build.PENDING))
        inprogress_builds = list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS))

        data['config'] = {
            'name': config.name, 'label': config.label, 'path': config.path,
            'min_rev': config.min_rev,
            'min_rev_href': req.href.changeset(config.min_rev),
            'max_rev': config.max_rev,
            'max_rev_href': req.href.changeset(config.max_rev),
            'active': config.active, 'description': description,
            'browser_href': req.href.browser(config.path),
            'builds_pending' : len(pending_builds),
	    'builds_inprogress' : len(inprogress_builds)
        }

        platforms = list(TargetPlatform.select(self.env, config=config_name,
                                               db=db))
        data['config']['platforms'] = [
            { 'name': platform.name,
              'id': platform.id, 
              'builds_pending': len(list(Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))),
              'builds_inprogress': len(list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id)))
              }
            for platform in platforms
        ]

        has_reports = False
        for report in Report.select(self.env, config=config.name, db=db):
            has_reports = True
            break

        if has_reports:
            chart_generators = []
            for generator in ReportChartController(self.env).generators: 
                for category in generator.get_supported_categories(): 
                    chart_generators.append({
                        'href': req.href.build(config.name, 'chart/' + category) 
                    })
            data['config']['charts'] = chart_generators 
            charts_license = self.config.get('bitten', 'charts_license')
            if charts_license:
                data['config']['charts_license'] = charts_license

        page = max(1, int(req.args.get('page', 1)))
        more = False
        data['page_number'] = page

        repos = self.env.get_repository(req.authname)
        if hasattr(repos, 'sync'):
            repos.sync()

        builds_per_page = 12 * len(platforms)
        idx = 0
        builds = {}
        for platform, rev, build in collect_changes(repos, config):
            if idx >= page * builds_per_page:
                more = True
                break
            elif idx >= (page - 1) * builds_per_page:
                builds.setdefault(rev, {})
                builds[rev].setdefault('href', req.href.changeset(rev))
                if build and build.status != Build.PENDING:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['steps'] = []
                    for step in BuildStep.select(self.env, build=build.id,
                                                 db=db):
                        build_data['steps'].append({
                            'name': step.name,
                            'description': step.description,
                            'duration': datetime.fromtimestamp(step.stopped) - \
                                        datetime.fromtimestamp(step.started),
                            'failed': not step.successful,
                            'errors': step.errors,
                            'href': build_data['href'] + '#step_' + step.name
                        })
                    builds[rev][platform.id] = build_data
            idx += 1
        data['config']['builds'] = builds

        if page > 1:
            if page == 2:
                prev_href = req.href.build(config.name)
            else:
                prev_href = req.href.build(config.name, page=page - 1)
            add_link(req, 'prev', prev_href, 'Previous Page')
        if more:
            next_href = req.href.build(config.name, page=page + 1)
            add_link(req, 'next', next_href, 'Next Page')
        prevnext_nav(req, 'Page')
        return data
Exemple #14
0
    def _render_overview(self, req):
        data = {'title': 'Build Status'}
        show_all = False
        if req.args.get('show') == 'all':
            show_all = True
        data['show_all'] = show_all

        repos = self.env.get_repository(req.authname)
        if hasattr(repos, 'sync'):
            repos.sync()

        configs = []
        for config in BuildConfig.select(self.env, include_inactive=show_all):
            if not repos.authz.has_permission(config.path):
                continue

            description = config.description
            if description:
                description = wiki_to_html(description, self.env, req)

            platforms_data = []
            for platform in TargetPlatform.select(self.env, config=config.name):
                pd = { 'name': platform.name,
                       'id': platform.id,
                       'builds_pending': len(list(Build.select(self.env, config=config.name, status=Build.PENDING, platform=platform.id))),
                       'builds_inprogress': len(list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS, platform=platform.id)))
                }
                platforms_data.append(pd)
		
            config_data = {
                'name': config.name, 'label': config.label or config.name,
                'active': config.active, 'path': config.path,
                'description': description,
		'builds_pending' : len(list(Build.select(self.env, config=config.name, status=Build.PENDING))),
		'builds_inprogress' : len(list(Build.select(self.env, config=config.name, status=Build.IN_PROGRESS))),
                'href': req.href.build(config.name),
                'builds': [],
                'platforms': platforms_data
            }
            configs.append(config_data)
            if not config.active:
                continue

            prev_rev = None
            for platform, rev, build in collect_changes(repos, config):
                if rev != prev_rev:
                    if prev_rev is None:
                        chgset = repos.get_changeset(rev)
                        config_data['youngest_rev'] = {
                            'id': rev, 'href': req.href.changeset(rev),
                            'author': chgset.author or 'anonymous',
                            'date': format_datetime(chgset.date),
                            'message': wiki_to_oneliner(
                                shorten_line(chgset.message), self.env, req=req)
                        }
                    else:
                        break
                    prev_rev = rev
                if build:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['platform'] = platform.name
                    config_data['builds'].append(build_data)
                else:
                    config_data['builds'].append({
                        'platform': platform.name, 'status': 'pending'
                    })

        data['configs'] = configs
        data['page_mode'] = 'overview'

        in_progress_builds = Build.select(self.env, status=Build.IN_PROGRESS)
        pending_builds = Build.select(self.env, status=Build.PENDING)

	data['builds_pending'] = len(list(pending_builds))
	data['builds_inprogress'] = len(list(in_progress_builds))

        add_link(req, 'views', req.href.build(view='inprogress'),
                 'In Progress Builds')
        add_ctxtnav(req, 'In Progress Builds',
                    req.href.build(view='inprogress'))
        return data
Exemple #15
0
    def render_admin_panel(self, req, cat, page, path_info):
        data = {}

        # Analyze url
        try:
            config_name, platform_id = path_info.split('/', 1)
        except:
            config_name = path_info
            platform_id = None

        if config_name: # Existing build config
            warnings = []
            if platform_id or (
                    # Editing or creating one of the config's target platforms
                    req.method == 'POST' and 'new' in req.args):

                if platform_id: # Editing target platform
                    platform_id = int(platform_id)
                    platform = TargetPlatform.fetch(self.env, platform_id)

                    if req.method == 'POST':
                        if 'cancel' in req.args or \
                                self._update_platform(req, platform):
                            req.redirect(req.abs_href.admin(cat, page,
                                                            config_name))
                else: # creating target platform
                    platform = self._create_platform(req, config_name)
                    req.redirect(req.abs_href.admin(cat, page,
                                            config_name, platform.id))

                # Set up template variables
                data['platform'] = {
                    'id': platform.id, 'name': platform.name,
                    'exists': platform.exists,
                    'rules': [
                        {'property': propname, 'pattern': pattern}
                        for propname, pattern in platform.rules
                    ] or [('', '')]
                }

            else: # Editing existing build config itself
                config = BuildConfig.fetch(self.env, config_name)
                platforms = list(TargetPlatform.select(self.env,
                                                       config=config.name))

                if req.method == 'POST':
                    if 'remove' in req.args: # Remove selected platforms
                        self._remove_platforms(req)
                        add_notice(req, "Target Platform(s) Removed.")
                        req.redirect(req.abs_href.admin(cat, page, config.name))

                    elif 'save' in req.args: # Save this build config
                        warnings = self._update_config(req, config)

                    if not warnings:
                        add_notice(req, "Configuration Saved.")
                        req.redirect(req.abs_href.admin(cat, page, config.name))

                    for warning in warnings:
                        add_warning(req, warning)

                # FIXME: Deprecation notice for old namespace.
                # Remove notice code when migration to new namespace is complete
                if 'http://bitten.cmlenz.net/tools/' in config.recipe:
                    add_notice(req, "Recipe uses a deprecated namespace. "
                        "Replace 'http://bitten.cmlenz.net/tools/' with "
                        "'http://bitten.edgewall.org/tools/'.")

                # Add a notice if configuration is not active
                if not warnings and not config.active and config.recipe:
                    add_notice(req, "Configuration is not active. Activate "
                        "from main 'Configurations' listing to enable it.")

                # Prepare template variables
                data['config'] = {
                    'name': config.name, 'label': config.label or config.name,
                    'active': config.active, 'path': config.path,
                    'min_rev': config.min_rev, 'max_rev': config.max_rev,
                    'description': config.description,
                    'recipe': config.recipe,
                    'platforms': [{
                        'name': platform.name,
                        'id': platform.id,
                        'href': req.href.admin('bitten', 'configs', config.name,
                                               platform.id),
                        'rules': [{'property': propname, 'pattern': pattern}
                                   for propname, pattern in platform.rules]
                    } for platform in platforms]
                }

        else: # At the top level build config list
            if req.method == 'POST':
                if 'add' in req.args: # Add build config
                    config = self._create_config(req)
                    req.redirect(req.abs_href.admin(cat, page, config.name))

                elif 'remove' in req.args: # Remove selected build configs
                    self._remove_configs(req)

                elif 'apply' in req.args: # Update active state of configs
                    self._activate_configs(req)
                req.redirect(req.abs_href.admin(cat, page))

            # Prepare template variables
            configs = []
            for config in BuildConfig.select(self.env, include_inactive=True):
                configs.append({
                    'name': config.name, 'label': config.label or config.name,
                    'active': config.active, 'path': config.path,
                    'min_rev': config.min_rev, 'max_rev': config.max_rev,
                    'href': req.href.admin('bitten', 'configs', config.name),
                    'recipe': config.recipe and True or False
                })
            data['configs'] = sorted(configs, key=lambda x:x['label'].lower())

        add_stylesheet(req, 'bitten/admin.css')
        add_script(req, 'common/js/suggest.js')
        return 'bitten_admin_configs.html', data
Exemple #16
0
    def render_admin_panel(self, req, cat, page, path_info):
        data = {}

        # Analyze url
        try:
            config_name, platform_id = path_info.split('/', 1)
        except:
            config_name = path_info
            platform_id = None

        if config_name:  # Existing build config
            warnings = []
            if platform_id or (
                    # Editing or creating one of the config's target platforms
                    req.method == 'POST' and 'new' in req.args):

                if platform_id:  # Editing target platform
                    platform_id = int(platform_id)
                    platform = TargetPlatform.fetch(self.env, platform_id)

                    if req.method == 'POST':
                        if 'cancel' in req.args or \
                                self._update_platform(req, platform):
                            req.redirect(
                                req.abs_href.admin(cat, page, config_name))
                else:  # creating target platform
                    platform = self._create_platform(req, config_name)
                    req.redirect(
                        req.abs_href.admin(cat, page, config_name,
                                           platform.id))

                # Set up template variables
                data['platform'] = {
                    'id':
                    platform.id,
                    'name':
                    platform.name,
                    'exists':
                    platform.exists,
                    'rules': [{
                        'property': propname,
                        'pattern': pattern
                    } for propname, pattern in platform.rules] or [('', '')]
                }

            else:  # Editing existing build config itself
                config = BuildConfig.fetch(self.env, config_name)
                platforms = list(
                    TargetPlatform.select(self.env, config=config.name))

                if req.method == 'POST':
                    if 'remove' in req.args:  # Remove selected platforms
                        self._remove_platforms(req)
                        add_notice(req, "Target Platform(s) Removed.")
                        req.redirect(req.abs_href.admin(
                            cat, page, config.name))

                    elif 'save' in req.args:  # Save this build config
                        warnings = self._update_config(req, config)

                    if not warnings:
                        add_notice(req, "Configuration Saved.")
                        req.redirect(req.abs_href.admin(
                            cat, page, config.name))

                    for warning in warnings:
                        add_warning(req, warning)

                # FIXME: Deprecation notice for old namespace.
                # Remove notice code when migration to new namespace is complete
                if 'http://bitten.cmlenz.net/tools/' in config.recipe:
                    add_notice(
                        req, "Recipe uses a deprecated namespace. "
                        "Replace 'http://bitten.cmlenz.net/tools/' with "
                        "'http://bitten.edgewall.org/tools/'.")

                # Add a notice if configuration is not active
                if not warnings and not config.active and config.recipe:
                    add_notice(
                        req, "Configuration is not active. Activate "
                        "from main 'Configurations' listing to enable it.")

                # Prepare template variables
                data['config'] = {
                    'name':
                    config.name,
                    'label':
                    config.label or config.name,
                    'active':
                    config.active,
                    'branch':
                    config.branch,
                    'description':
                    config.description,
                    'recipe':
                    config.recipe,
                    'platforms': [{
                        'name':
                        platform.name,
                        'id':
                        platform.id,
                        'href':
                        req.href.admin('bitten', 'configs', config.name,
                                       platform.id),
                        'rules': [{
                            'property': propname,
                            'pattern': pattern
                        } for propname, pattern in platform.rules]
                    } for platform in platforms]
                }

        else:  # At the top level build config list
            if req.method == 'POST':
                if 'add' in req.args:  # Add build config
                    config = self._create_config(req)
                    req.redirect(req.abs_href.admin(cat, page, config.name))

                elif 'remove' in req.args:  # Remove selected build configs
                    self._remove_configs(req)

                elif 'apply' in req.args:  # Update active state of configs
                    self._activate_configs(req)
                req.redirect(req.abs_href.admin(cat, page))

            # Prepare template variables
            configs = []
            for config in BuildConfig.select(self.env, include_inactive=True):
                configs.append({
                    'name':
                    config.name,
                    'label':
                    config.label or config.name,
                    'active':
                    config.active,
                    'branch':
                    config.branch,
                    'href':
                    req.href.admin('bitten', 'configs', config.name),
                    'recipe':
                    config.recipe and True or False
                })
            data['configs'] = configs

        add_stylesheet(req, 'bitten/admin.css')
        add_script(req, 'common/js/suggest.js')
        return 'bitten_admin_configs.html', data
Exemple #17
0
    def _render_config(self, req, config_name):
        db = self.env.get_db_cnx()

        config = BuildConfig.fetch(self.env, config_name, db=db)
        if not config:
            raise HTTPNotFound("Build configuration '%s' does not exist." \
                                % config_name)

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'
        rev = config.max_rev or repos.youngest_rev
        try:
            _has_permission(req.perm, repos, config.path, rev=rev,
                                                        raise_error=True)
        except NoSuchNode:
            raise TracError("Permission checking against repository path %s "
                "at revision %s failed." % (config.path, rev))

        data = {'title': 'Build Configuration "%s"' \
                          % config.label or config.name,
                'page_mode': 'view_config'}
        add_link(req, 'up', req.href.build(), 'Build Status')
        description = config.description
        if description:
            description = wiki_to_html(description, self.env, req)

        pending_builds = list(Build.select(self.env,
                                config=config.name, status=Build.PENDING))
        inprogress_builds = list(Build.select(self.env,
                                config=config.name, status=Build.IN_PROGRESS))

        data['config'] = {
            'name': config.name, 'label': config.label, 'path': config.path,
            'min_rev': config.min_rev,
            'min_rev_href': req.href.changeset(config.min_rev),
            'max_rev': config.max_rev,
            'max_rev_href': req.href.changeset(config.max_rev),
            'active': config.active, 'description': description,
            'browser_href': req.href.browser(config.path),
            'builds_pending' : len(pending_builds),
            'builds_inprogress' : len(inprogress_builds)
        }

        context = Context.from_request(req, config.resource)
        data['context'] = context
        data['config']['attachments'] = AttachmentModule(self.env).attachment_data(context)

        platforms = list(TargetPlatform.select(self.env, config=config_name,
                                               db=db))
        data['config']['platforms'] = [
            { 'name': platform.name,
              'id': platform.id,
              'builds_pending': len(list(Build.select(self.env,
                                                    config=config.name,
                                                    status=Build.PENDING,
                                                    platform=platform.id))),
              'builds_inprogress': len(list(Build.select(self.env,
                                                    config=config.name,
                                                    status=Build.IN_PROGRESS,
                                                    platform=platform.id)))
              }
            for platform in platforms
        ]

        has_reports = False
        for report in Report.select(self.env, config=config.name, db=db):
            has_reports = True
            break

        if has_reports:
            chart_generators = []
            report_categories = list(self._report_categories_for_config(config))
            for generator in ReportChartController(self.env).generators:
                for category in generator.get_supported_categories():
                    if category in report_categories:
                        chart_generators.append({
                            'href': req.href.build(config.name, 'chart/' + category),
                            'category': category,
                            'style': self.config.get('bitten', 'chart_style'),
                        })
            data['config']['charts'] = chart_generators

        page = max(1, int(req.args.get('page', 1)))
        more = False
        data['page_number'] = page

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'

        builds_per_page = 12 * len(platforms)
        idx = 0
        builds = {}
        revisions = []
        for platform, rev, build in collect_changes(repos, config):
            if idx >= page * builds_per_page:
                more = True
                break
            elif idx >= (page - 1) * builds_per_page:
                if rev not in builds:
                    revisions.append(rev)
                builds.setdefault(rev, {})
                builds[rev].setdefault('href', req.href.changeset(rev))
                builds[rev].setdefault('display_rev', repos.normalize_rev(rev))
                if build and build.status != Build.PENDING:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['steps'] = []
                    for step in BuildStep.select(self.env, build=build.id,
                                                 db=db):
                        build_data['steps'].append({
                            'name': step.name,
                            'description': step.description,
                            'duration': to_datetime(step.stopped or int(time.time()), utc) - \
                                        to_datetime(step.started, utc),
                            'status': _step_status_label[step.status],
                            'cls': _step_status_label[step.status].replace(' ', '-'),

                            'errors': step.errors,
                            'href': build_data['href'] + '#step_' + step.name
                        })
                    builds[rev][platform.id] = build_data
            idx += 1
        data['config']['builds'] = builds
        data['config']['revisions'] = revisions

        if page > 1:
            if page == 2:
                prev_href = req.href.build(config.name)
            else:
                prev_href = req.href.build(config.name, page=page - 1)
            add_link(req, 'prev', prev_href, 'Previous Page')
        if more:
            next_href = req.href.build(config.name, page=page + 1)
            add_link(req, 'next', next_href, 'Next Page')
        if arity(prevnext_nav) == 4: # Trac 0.12 compat, see #450
            prevnext_nav(req, 'Previous Page', 'Next Page')
        else:
            prevnext_nav (req, 'Page')
        return data
Exemple #18
0
        if config.max_rev and repos.rev_older_than(config.max_rev, rev):
            continue

        # Make sure the repository directory isn't empty at this
        # revision
        old_node = repos.get_node(path, rev)
        is_empty = True
        for entry in old_node.get_entries():
            is_empty = False
            break
        if is_empty:
            continue

        # For every target platform, check whether there's a build
        # of this revision
        for platform in TargetPlatform.select(env, config.name, db=db):
            builds = list(Build.select(env, config.name, rev, platform.id,
                                       db=db))
            if builds:
                build = builds[0]
            else:
                build = None

            yield platform, rev, build


class BuildQueue(object):
    """Enapsulates the build queue of an environment.
    
    A build queue manages the the registration of build slaves and detection of
    repository revisions that need to be built.
Exemple #19
0
    def _render_overview(self, req):
        data = {'title': 'Build Status'}
        show_all = False
        if req.args.get('show') == 'all':
            show_all = True
        data['show_all'] = show_all

        repos = self.env.get_repository(authname=req.authname)
        assert repos, 'No "(default)" Repository: Add a repository or alias ' \
                      'named "(default)" to Trac.'

        configs = []
        for config in BuildConfig.select(self.env, include_inactive=show_all):
            rev = config.max_rev or repos.youngest_rev
            try:
                if not _has_permission(req.perm, repos, config.path, rev=rev):
                    continue
            except NoSuchNode:
                add_warning(req, "Configuration '%s' points to non-existing "
                        "path '/%s' at revision '%s'. Configuration skipped." \
                                    % (config.name, config.path, rev))
                continue

            description = config.description
            if description:
                description = wiki_to_html(description, self.env, req)

            platforms_data = []
            for platform in TargetPlatform.select(self.env,
                                                  config=config.name):
                pd = {
                    'name':
                    platform.name,
                    'id':
                    platform.id,
                    'builds_pending':
                    len(
                        list(
                            Build.select(self.env,
                                         config=config.name,
                                         status=Build.PENDING,
                                         platform=platform.id))),
                    'builds_inprogress':
                    len(
                        list(
                            Build.select(self.env,
                                         config=config.name,
                                         status=Build.IN_PROGRESS,
                                         platform=platform.id)))
                }
                platforms_data.append(pd)

            config_data = {
                'name':
                config.name,
                'label':
                config.label or config.name,
                'active':
                config.active,
                'path':
                config.path,
                'description':
                description,
                'builds_pending':
                len(
                    list(
                        Build.select(self.env,
                                     config=config.name,
                                     status=Build.PENDING))),
                'builds_inprogress':
                len(
                    list(
                        Build.select(self.env,
                                     config=config.name,
                                     status=Build.IN_PROGRESS))),
                'href':
                req.href.build(config.name),
                'builds': [],
                'platforms':
                platforms_data
            }
            configs.append(config_data)
            if not config.active:
                continue

            prev_rev = None
            for platform, rev, build in collect_changes(repos, config):
                if rev != prev_rev:
                    if prev_rev is None:
                        chgset = repos.get_changeset(rev)
                        config_data['youngest_rev'] = {
                            'id':
                            rev,
                            'href':
                            req.href.changeset(rev),
                            'display_rev':
                            repos.normalize_rev(rev),
                            'author':
                            chgset.author or 'anonymous',
                            'date':
                            format_datetime(chgset.date),
                            'message':
                            wiki_to_oneliner(shorten_line(chgset.message),
                                             self.env,
                                             req=req)
                        }
                    else:
                        break
                    prev_rev = rev
                if build:
                    build_data = _get_build_data(self.env, req, build)
                    build_data['platform'] = platform.name
                    config_data['builds'].append(build_data)
                else:
                    config_data['builds'].append({
                        'platform': platform.name,
                        'status': 'pending'
                    })

        data['configs'] = sorted(configs, key=lambda x: x['label'].lower())
        data['page_mode'] = 'overview'

        in_progress_builds = Build.select(self.env, status=Build.IN_PROGRESS)
        pending_builds = Build.select(self.env, status=Build.PENDING)

        data['builds_pending'] = len(list(pending_builds))
        data['builds_inprogress'] = len(list(in_progress_builds))

        add_link(req, 'views', req.href.build(view='inprogress'),
                 'In Progress Builds')
        add_ctxtnav(req, 'In Progress Builds',
                    req.href.build(view='inprogress'))
        return data