def getProjectId(self, sourcestamp):
        # retrieve project id via cache
        url = giturlparse(sourcestamp['repository'])
        if url is None:
            defer.returnValue(None)
        project_full_name = u"%s/%s" % (url.owner, url.repo)
        project_full_name = unicode2NativeString(project_full_name)

        # gitlab needs project name to be fully url quoted to get the project id
        project_full_name = urlquote_plus(project_full_name)

        if project_full_name not in self.project_ids:
            response = yield self._http.get('/api/v3/projects/%s' % (project_full_name))
            proj = yield response.json()
            if response.code not in (200, ):
                log.msg(
                    'Unknown (or hidden) gitlab project'
                    '{repo}: {message}'.format(
                        repo=project_full_name, **proj))
                defer.returnValue(None)
            self.project_ids[project_full_name] = proj['id']

        defer.returnValue(self.project_ids[project_full_name])
Esempio n. 2
0
    def create_changes(self, new_logentries):
        changes = []

        for el in new_logentries:
            revision = text_type(el.getAttribute("revision"))

            revlink = u''

            if self.revlinktmpl and revision:
                revlink = self.revlinktmpl % urlquote_plus(revision)
                revlink = text_type(revlink)

            log.msg("Adding change revision %s" % (revision,))
            author = self._get_text(el, "author")
            comments = self._get_text(el, "msg")
            # there is a "date" field, but it provides localtime in the
            # repository's timezone, whereas we care about buildmaster's
            # localtime (since this will get used to position the boxes on
            # the Waterfall display, etc). So ignore the date field, and
            # addChange will fill in with the current time
            branches = {}
            try:
                pathlist = el.getElementsByTagName("paths")[0]
            except IndexError:  # weird, we got an empty revision
                log.msg("ignoring commit with no paths")
                continue

            for p in pathlist.getElementsByTagName("path"):
                kind = p.getAttribute("kind")
                action = p.getAttribute("action")
                path = u"".join([t.data for t in p.childNodes])
                if path.startswith("/"):
                    path = path[1:]
                if kind == "dir" and not path.endswith("/"):
                    path += "/"
                where = self._transform_path(path)

                # if 'where' is None, the file was outside any project that
                # we care about and we should ignore it
                if where:
                    branch = where.get("branch", None)
                    filename = where["path"]
                    if branch not in branches:
                        branches[branch] = {
                            'files': [], 'number_of_directories': 0}
                    if filename == "":
                        # root directory of branch
                        branches[branch]['files'].append(filename)
                        branches[branch]['number_of_directories'] += 1
                    elif filename.endswith("/"):
                        # subdirectory of branch
                        branches[branch]['files'].append(filename[:-1])
                        branches[branch]['number_of_directories'] += 1
                    else:
                        branches[branch]['files'].append(filename)

                    if "action" not in branches[branch]:
                        branches[branch]['action'] = action

                    for key in ("repository", "project", "codebase"):
                        if key in where:
                            branches[branch][key] = where[key]

            for branch in branches:
                action = branches[branch]['action']
                files = branches[branch]['files']

                number_of_directories_changed = branches[
                    branch]['number_of_directories']
                number_of_files_changed = len(files)

                if (action == u'D' and number_of_directories_changed == 1 and
                        number_of_files_changed == 1 and files[0] == ''):
                    log.msg("Ignoring deletion of branch '%s'" % branch)
                else:
                    chdict = dict(
                        author=author,
                        # weakly assume filenames are utf-8
                        files=[bytes2unicode(f, 'utf-8', 'replace')
                               for f in files],
                        comments=comments,
                        revision=revision,
                        branch=util.bytes2unicode(branch),
                        revlink=revlink,
                        category=self.category,
                        repository=util.bytes2unicode(
                            branches[branch].get('repository', self.repourl)),
                        project=util.bytes2unicode(
                            branches[branch].get('project', self.project)),
                        codebase=util.bytes2unicode(
                            branches[branch].get('codebase', None)))
                    changes.append(chdict)

        return changes
Esempio n. 3
0
    def create_changes(self, new_logentries):
        changes = []

        for el in new_logentries:
            revision = text_type(el.getAttribute("revision"))

            revlink = u''

            if self.revlinktmpl and revision:
                revlink = self.revlinktmpl % urlquote_plus(revision)
                revlink = text_type(revlink)

            log.msg("Adding change revision %s" % (revision, ))
            author = self._get_text(el, "author")
            comments = self._get_text(el, "msg")
            # there is a "date" field, but it provides localtime in the
            # repository's timezone, whereas we care about buildmaster's
            # localtime (since this will get used to position the boxes on
            # the Waterfall display, etc). So ignore the date field, and
            # addChange will fill in with the current time
            branches = {}
            try:
                pathlist = el.getElementsByTagName("paths")[0]
            except IndexError:  # weird, we got an empty revision
                log.msg("ignoring commit with no paths")
                continue

            for p in pathlist.getElementsByTagName("path"):
                kind = p.getAttribute("kind")
                action = p.getAttribute("action")
                path = "".join([t.data for t in p.childNodes])
                path = path.encode("ascii")
                if path.startswith("/"):
                    path = path[1:]
                if kind == "dir" and not path.endswith("/"):
                    path += "/"
                where = self._transform_path(path)

                # if 'where' is None, the file was outside any project that
                # we care about and we should ignore it
                if where:
                    branch = where.get("branch", None)
                    filename = where["path"]
                    if branch not in branches:
                        branches[branch] = {
                            'files': [],
                            'number_of_directories': 0
                        }
                    if filename == "":
                        # root directory of branch
                        branches[branch]['files'].append(filename)
                        branches[branch]['number_of_directories'] += 1
                    elif filename.endswith("/"):
                        # subdirectory of branch
                        branches[branch]['files'].append(filename[:-1])
                        branches[branch]['number_of_directories'] += 1
                    else:
                        branches[branch]['files'].append(filename)

                    if "action" not in branches[branch]:
                        branches[branch]['action'] = action

                    for key in ("repository", "project", "codebase"):
                        if key in where:
                            branches[branch][key] = where[key]

            for branch in branches:
                action = branches[branch]['action']
                files = branches[branch]['files']

                number_of_directories_changed = branches[branch][
                    'number_of_directories']
                number_of_files_changed = len(files)

                if action == u'D' and number_of_directories_changed == 1 and number_of_files_changed == 1 and files[
                        0] == '':
                    log.msg("Ignoring deletion of branch '%s'" % branch)
                else:
                    chdict = dict(
                        author=author,
                        # weakly assume filenames are utf-8
                        files=[f.decode('utf-8', 'replace') for f in files],
                        comments=comments,
                        revision=revision,
                        branch=util.ascii2unicode(branch),
                        revlink=revlink,
                        category=self.category,
                        repository=util.ascii2unicode(branches[branch].get(
                            'repository', self.repourl)),
                        project=util.ascii2unicode(branches[branch].get(
                            'project', self.project)),
                        codebase=util.ascii2unicode(branches[branch].get(
                            'codebase', None)))
                    changes.append(chdict)

        return changes
Esempio n. 4
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])

        if build['complete']:
            state = {
                SUCCESS: 'success',
                WARNINGS: 'success',
                FAILURE: 'failed',
                SKIPPED: 'success',
                EXCEPTION: 'error',
                RETRY: 'pending',
                CANCELLED: 'error'
            }.get(build['results'], 'error')
            description = yield props.render(self.endDescription)
        else:
            state = 'running'
            description = yield props.render(self.startDescription)

        context = yield props.render(self.context)

        sourcestamps = build['buildset']['sourcestamps']
        project = sourcestamps[0]['project']

        for ss in sourcestamps:
            try:
                repo = ss['repository'].split('/')[-2:]
                repoOwner = repo[0]
                if repo[1].endswith(".git"):
                    repoName = '.'.join(repo[1].split('.')[:-1])
                else:
                    repoName = repo[1]
                # default to master if not found
                branch = ss.get('branch', 'master')
                break
            except Exception:
                pass

        if project and len(project.split('/')) == 2:
            repoOwner, repoName = project.split('/')

        m = re.match(".*:(.*)", repoOwner)
        if m is not None:
            repoOwner = m.group(1)

        # retrieve project id via cache

        project_full_name = u"%s/%s" % (repoOwner, repoName)
        project_full_name = unicode2NativeString(project_full_name)

        # gitlab needs project name to be fully url quoted to get the project id
        project_full_name = urlquote_plus(project_full_name)

        if project_full_name not in self.project_ids:
            proj = yield self._http.get('/api/v3/projects/%s' %
                                        (project_full_name))
            proj = yield proj.json()
            self.project_ids[project_full_name] = proj['id']

        proj_id = self.project_ids[project_full_name]
        for sourcestamp in sourcestamps:
            sha = sourcestamp['revision']
            try:
                branch = unicode2NativeString(branch)
                sha = unicode2NativeString(sha)
                state = unicode2NativeString(state)
                target_url = unicode2NativeString(build['url'])
                context = unicode2NativeString(context)
                description = unicode2NativeString(description)
                res = yield self.createStatus(project_id=proj_id,
                                              branch=branch,
                                              sha=sha,
                                              state=state,
                                              target_url=target_url,
                                              context=context,
                                              description=description)
                if res.code not in (200, 201, 204):
                    message = yield res.json()
                    message = message.get('message', 'unspecified error')
                    log.msg(
                        'Could not send status "{state}" for '
                        '{repoOwner}/{repoName} at {sha}: {message}'.format(
                            state=state,
                            repoOwner=repoOwner,
                            repoName=repoName,
                            sha=sha,
                            message=message))
                elif self.verbose:
                    log.msg('Status "{state}" sent for '
                            '{repoOwner}/{repoName} at {sha}.'.format(
                                state=state,
                                repoOwner=repoOwner,
                                repoName=repoName,
                                sha=sha))
            except Exception as e:
                log.err(
                    e, 'Fail to send status "{state}" for '
                    '{repoOwner}/{repoName} at {sha}'.format(
                        state=state,
                        repoOwner=repoOwner,
                        repoName=repoName,
                        sha=sha))