Beispiel #1
0
    def _extract_github_params(self, sourcestamp, branch=None):
        """Parses parameters required to by github

        License note:
            Contains copied parts from the original buildbot implementation.
        """
        # branch is updated by the checkoutstep, required for PRs
        branch = branch or sourcestamp['branch']
        project = sourcestamp['project']
        repo = sourcestamp['repository']
        sha = sourcestamp['revision']

        # determine whether the branch refers to a PR
        m = re.search(r'refs/pull/([0-9]*)/merge', branch)
        if m:
            issue = m.group(1)
        else:
            issue = None

        if '/' in project:
            repo_owner, repo_name = project.split('/')
        else:
            giturl = giturlparse(repo)
            repo_owner, repo_name = giturl.owner, giturl.repo

        return dict(sha=sha,
                    repo=repo,
                    branch=branch,
                    issue=issue,
                    repo_owner=repo_owner,
                    repo_name=repo_name)
Beispiel #2
0
    def _extract_github_info(self, sourcestamp):
        repo_owner = None
        repo_name = None
        project = sourcestamp['project']
        repository = sourcestamp['repository']
        if project and "/" in project:
            repo_owner, repo_name = project.split('/')
        elif repository:
            giturl = giturlparse(repository)
            if giturl:
                repo_owner = giturl.owner
                repo_name = giturl.repo

        return repo_owner, repo_name
Beispiel #3
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')

        if not sourcestamps or not sourcestamps[0]:
            return

        project = sourcestamps[0]['project']

        branch = props['branch']
        m = re.search(r"refs/pull/([0-9]*)/merge", branch)
        if m:
            issue = m.group(1)
        else:
            issue = None

        if "/" in project:
            repoOwner, repoName = project.split('/')
        else:
            giturl = giturlparse(sourcestamps[0]['repository'])
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg(
                "Updating github status: repoOwner={repoOwner}, repoName={repoName}"
                .format(repoOwner=repoOwner, repoName=repoName))

        for sourcestamp in sourcestamps:
            sha = sourcestamp['revision']
            try:
                repo_user = unicode2NativeString(repoOwner)
                repo_name = unicode2NativeString(repoName)
                sha = unicode2NativeString(sha)
                state = unicode2NativeString(state)
                target_url = unicode2NativeString(build['url'])
                context = unicode2NativeString(context)
                issue = unicode2NativeString(issue)
                description = unicode2NativeString(description)
                yield self.createStatus(repo_user=repo_user,
                                        repo_name=repo_name,
                                        sha=sha,
                                        state=state,
                                        target_url=target_url,
                                        context=context,
                                        issue=issue,
                                        description=description)
                if self.verbose:
                    log.msg('Updated status with "{state}" for '
                            '{repoOwner}/{repoName} at {sha}, issue {issue}.'.
                            format(state=state,
                                   repoOwner=repoOwner,
                                   repoName=repoName,
                                   sha=sha,
                                   issue=issue))
            except Exception as e:
                log.err(
                    e, 'Failed to update "{state}" for '
                    '{repoOwner}/{repoName} at {sha}, issue {issue}'.format(
                        state=state,
                        repoOwner=repoOwner,
                        repoName=repoName,
                        sha=sha,
                        issue=issue))
    def send(self, build):
        props = Properties.fromDict(build["properties"])
        props.master = self.master

        if build["complete"]:
            state = {
                SUCCESS: "success",
                WARNINGS: "success",
                FAILURE: "failure",
                SKIPPED: "success",
                EXCEPTION: "error",
                RETRY: "pending",
                CANCELLED: "error",
            }.get(build["results"], "error")
        else:
            return

        if state != "failure":
            return

        yield getDetailsForBuild(self.master, build, wantLogs=True, wantSteps=True)

        tracebacks = list()
        try:
            test_log = build["steps"][TESTS_STEP]["logs"][0]["content"]["content"]
            test_log = "\n".join([line.lstrip("eo") for line in test_log.splitlines()])
            tracebacks = TRACEBACK_REGEX.findall(test_log)
        except IndexError:
            pass

        if not tracebacks:
            tracebacks = list(self._construct_tracebacks_from_stderr(build))

        context = yield props.render(self.context)

        sourcestamps = build["buildset"].get("sourcestamps")

        if not sourcestamps or not sourcestamps[0]:
            return

        changes = yield self.master.data.get(("builds", build["buildid"], "changes"))

        if len(changes) > 1:
            return

        change, = changes

        m = re.search(r"\((?:GH-|#)(\d+)\)", change["comments"])

        if m is None:
            return

        issue = m.groups()[-1]

        project = sourcestamps[0]["project"]

        if "/" in project:
            repoOwner, repoName = project.split("/")
        else:
            giturl = giturlparse(sourcestamps[0]["repository"])
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg(
                "Updating github status: repoOwner={repoOwner}, repoName={repoName}".format(
                    repoOwner=repoOwner, repoName=repoName
                )
            )

        try:
            repo_user = unicode2NativeString(repoOwner)
            repo_name = unicode2NativeString(repoName)
            sha = unicode2NativeString(change["revision"])
            target_url = unicode2NativeString(build["url"])
            context = unicode2NativeString(context)
            yield self.createStatus(
                build=build,
                repo_user=repo_user,
                repo_name=repo_name,
                sha=sha,
                state=state,
                target_url=target_url,
                context=context,
                issue=issue,
                tracebacks=tracebacks,
            )
            if self.verbose:
                log.msg(
                    "Issued a Pull Request comment for {repoOwner}/{repoName} "
                    'at {sha}, context "{context}", issue {issue}.'.format(
                        repoOwner=repoOwner,
                        repoName=repoName,
                        sha=sha,
                        issue=issue,
                        context=context,
                    )
                )
        except Exception as e:
            log.err(
                e,
                "Failed to issue a Pull Request comment for {repoOwner}/{repoName} "
                'at {sha}, context "{context}", issue {issue}.'.format(
                    repoOwner=repoOwner,
                    repoName=repoName,
                    sha=sha,
                    issue=issue,
                    context=context,
                ),
            )
Beispiel #5
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])
        props.master = self.master

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')
        if not sourcestamps:
            return

        for sourcestamp in sourcestamps:
            project = sourcestamp['project']

            issue = None
            if 'branch' in props:
                m = re.search(r"refs/pull/([0-9]*)/merge", props['branch'])
                if m:
                    issue = m.group(1)

            repo_owner = None
            repo_name = None
            if "/" in project:
                repo_owner, repo_name = project.split('/')
            else:
                giturl = giturlparse(sourcestamp['repository'])
                if giturl:
                    repo_owner = giturl.owner
                    repo_name = giturl.repo

            sha = sourcestamp['revision']
            response = None

            # If the scheduler specifies multiple codebases, don't bother updating
            # the ones for which there is no revision
            if not sha:
                log.msg('Skipped status update for codebase {codebase}, '
                        'context "{context}", issue {issue}.'.format(
                            codebase=sourcestamp['codebase'],
                            issue=issue,
                            context=context))
                continue

            try:
                if self.verbose:
                    log.msg(
                        "Updating github status: repo_owner={}, repo_name={}".
                        format(repo_owner, repo_name))

                response = yield self.createStatus(repo_user=repo_owner,
                                                   repo_name=repo_name,
                                                   sha=sha,
                                                   state=state,
                                                   target_url=build['url'],
                                                   context=context,
                                                   issue=issue,
                                                   description=description)

                if not response:
                    # the implementation of createStatus refused to post update due to missing data
                    continue

                if not self.isStatus2XX(response.code):
                    raise Exception()

                if self.verbose:
                    log.msg(
                        'Updated status with "{state}" for {repo_owner}/{repo_name} '
                        'at {sha}, context "{context}", issue {issue}.'.format(
                            state=state,
                            repo_owner=repo_owner,
                            repo_name=repo_name,
                            sha=sha,
                            issue=issue,
                            context=context))
            except Exception as e:
                if response:
                    content = yield response.content()
                    code = response.code
                else:
                    content = code = "n/a"
                log.err(
                    e,
                    'Failed to update "{state}" for {repo_owner}/{repo_name} '
                    'at {sha}, context "{context}", issue {issue}. '
                    'http {code}, {content}'.format(state=state,
                                                    repo_owner=repo_owner,
                                                    repo_name=repo_name,
                                                    sha=sha,
                                                    issue=issue,
                                                    context=context,
                                                    code=code,
                                                    content=content))
    def send(self, build):
        props = Properties.fromDict(build['properties'])
        props.master = self.master

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')

        if not sourcestamps or not sourcestamps[0]:
            return

        branch = props['branch']
        m = re.search(r"refs/pull/([0-9]*)/merge", branch)
        if m:
            issue = m.group(1)
        else:
            # We only want to comment pull requests, so we exit here
            return

        for sourcestamp in sourcestamps:
            if branch == sourcestamp['branch']:
                project = sourcestamp['project']
                repository = sourcestamp['repository']
                sha = sourcestamp['revision']
                break

        if project is None:
            log.err('Failed to determine the project of PR "{branch}"'.format(
                    branch=branch))
            return

        if "/" in project:
            repoOwner, repoName = project.split('/')
        else:
            giturl = giturlparse(repository)
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg("Updating github status: repoOwner={repoOwner}, repoName={repoName}".format(
                repoOwner=repoOwner, repoName=repoName))

        try:
            repo_user = unicode2NativeString(repoOwner)
            repo_name = unicode2NativeString(repoName)
            sha = unicode2NativeString(sha)
            state = unicode2NativeString(state)
            target_url = unicode2NativeString(build['url'])
            context = unicode2NativeString(context)
            issue = unicode2NativeString(issue)
            description = unicode2NativeString(description)
            yield self.createStatus(
                repo_user=repo_user,
                repo_name=repo_name,
                sha=sha,
                state=state,
                target_url=target_url,
                context=context,
                issue=issue,
                description=description
            )
            if self.verbose:
                log.msg(
                    'Updated status with "{state}" for {repoOwner}/{repoName} '
                    'at {sha}, context "{context}", issue {issue}.'.format(
                        state=state, repoOwner=repoOwner, repoName=repoName,
                        sha=sha, issue=issue, context=context))
        except Exception as e:
            log.err(
                e,
                'Failed to update "{state}" for {repoOwner}/{repoName} '
                'at {sha}, context "{context}", issue {issue}.'.format(
                    state=state, repoOwner=repoOwner, repoName=repoName,
                    sha=sha, issue=issue, context=context))
Beispiel #7
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])
        props.master = self.master

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')

        if not sourcestamps or not sourcestamps[0]:
            return

        branch = props['branch']
        m = re.search(r"refs/pull/([0-9]*)/merge", branch)
        if m:
            issue = m.group(1)
        else:
            # We only want to comment pull requests, so we exit here
            return

        for sourcestamp in sourcestamps:
            if branch == sourcestamp['branch']:
                project = sourcestamp['project']
                repository = sourcestamp['repository']
                sha = sourcestamp['revision']
                break

        if project is None:
            log.err('Failed to determine the project of PR "{branch}"'.format(
                branch=branch))
            return

        if "/" in project:
            repoOwner, repoName = project.split('/')
        else:
            giturl = giturlparse(repository)
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg(
                "Updating github status: repoOwner={repoOwner}, repoName={repoName}"
                .format(repoOwner=repoOwner, repoName=repoName))

        try:
            yield self.createStatus(repo_user=repoOwner,
                                    repo_name=repoName,
                                    sha=sha,
                                    state=state,
                                    target_url=build['url'],
                                    context=context,
                                    issue=issue,
                                    description=description)
            if self.verbose:
                log.msg(
                    'Updated status with "{state}" for {repoOwner}/{repoName} '
                    'at {sha}, context "{context}", issue {issue}.'.format(
                        state=state,
                        repoOwner=repoOwner,
                        repoName=repoName,
                        sha=sha,
                        issue=issue,
                        context=context))
        except Exception as e:
            log.err(
                e, 'Failed to update "{state}" for {repoOwner}/{repoName} '
                'at {sha}, context "{context}", issue {issue}.'.format(
                    state=state,
                    repoOwner=repoOwner,
                    repoName=repoName,
                    sha=sha,
                    issue=issue,
                    context=context))
Beispiel #8
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])
        props.master = self.master

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')

        if not sourcestamps or not sourcestamps[0]:
            return

        project = sourcestamps[0]['project']

        branch = props['branch']
        m = re.search(r"refs/pull/([0-9]*)/merge", branch)
        if m:
            issue = m.group(1)
        else:
            issue = None

        if "/" in project:
            repoOwner, repoName = project.split('/')
        else:
            giturl = giturlparse(sourcestamps[0]['repository'])
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg("Updating github status: repoOwner={repoOwner}, repoName={repoName}".format(
                repoOwner=repoOwner, repoName=repoName))

        for sourcestamp in sourcestamps:
            sha = sourcestamp['revision']
            try:
                repo_user = repoOwner
                repo_name = repoName
                target_url = build['url']
                response = yield self.createStatus(
                    repo_user=repo_user,
                    repo_name=repo_name,
                    sha=sha,
                    state=state,
                    target_url=target_url,
                    context=context,
                    issue=issue,
                    description=description
                )

                if not self.isStatus2XX(response.code):
                    raise Exception()

                if self.verbose:
                    log.msg(
                        'Updated status with "{state}" for {repoOwner}/{repoName} '
                        'at {sha}, context "{context}", issue {issue}.'.format(
                            state=state, repoOwner=repoOwner, repoName=repoName,
                            sha=sha, issue=issue, context=context))
            except Exception as e:
                content = yield response.content()
                log.err(
                    e,
                    'Failed to update "{state}" for {repoOwner}/{repoName} '
                    'at {sha}, context "{context}", issue {issue}. '
                    'http {code}, {content}'.format(
                        state=state, repoOwner=repoOwner, repoName=repoName,
                        sha=sha, issue=issue, context=context,
                        code=response.code, content=content))
Beispiel #9
0
    def send(self, build):
        props = Properties.fromDict(build["properties"])
        props.master = self.master

        if build["complete"]:
            state = {
                SUCCESS: "success",
                WARNINGS: "success",
                FAILURE: "failure",
                SKIPPED: "success",
                EXCEPTION: "error",
                RETRY: "pending",
                CANCELLED: "error",
            }.get(build["results"], "error")
        else:
            return

        if state != "failure":
            return

        yield getDetailsForBuild(self.master, build, wantLogs=True, wantSteps=True)

        logs, tracebacks = get_logs_and_tracebacks_from_build(build)

        context = yield props.render(self.context)

        sourcestamps = build["buildset"].get("sourcestamps")

        if not (sourcestamps and sourcestamps[0]):
            return

        changes = yield self.master.data.get(("builds", build["buildid"], "changes"))

        if len(changes) != 1:
            return

        change = changes[0]
        change_comments = change["comments"]

        if not change_comments:
            return

        m = re.search(r"\((?:GH-|#)(\d+)\)", change_comments)

        if m is None:
            return

        issue = m.groups()[-1]

        project = sourcestamps[0]["project"]

        if "/" in project:
            repoOwner, repoName = project.split("/")
        else:
            giturl = giturlparse(sourcestamps[0]["repository"])
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg(
                "Updating github status: repoOwner={repoOwner}, repoName={repoName}".format(
                    repoOwner=repoOwner, repoName=repoName
                )
            )

        try:
            repo_user = repoOwner
            repo_name = repoName
            sha = change["revision"]
            target_url = build["url"]
            context = context
            yield self.createStatus(
                build=build,
                repo_user=repo_user,
                repo_name=repo_name,
                sha=sha,
                state=state,
                target_url=target_url,
                context=context,
                issue=issue,
                tracebacks=tracebacks,
                logs=logs,
            )
            if self.verbose:
                log.msg(
                    "Issued a Pull Request comment for {repoOwner}/{repoName} "
                    'at {sha}, context "{context}", issue {issue}.'.format(
                        repoOwner=repoOwner,
                        repoName=repoName,
                        sha=sha,
                        issue=issue,
                        context=context,
                    )
                )
        except Exception as e:
            log.err(
                e,
                "Failed to issue a Pull Request comment for {repoOwner}/{repoName} "
                'at {sha}, context "{context}", issue {issue}.'.format(
                    repoOwner=repoOwner,
                    repoName=repoName,
                    sha=sha,
                    issue=issue,
                    context=context,
                ),
            )
Beispiel #10
0
    def send(self, build):
        props = Properties.fromDict(build['properties'])
        props.master = self.master

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

        context = yield props.render(self.context)

        sourcestamps = build['buildset'].get('sourcestamps')

        if not sourcestamps or not sourcestamps[0]:
            return

        project = sourcestamps[0]['project']

        branch = props['branch']
        m = re.search(r"refs/pull/([0-9]*)/merge", branch)
        if m:
            issue = m.group(1)
        else:
            issue = None

        if "/" in project:
            repoOwner, repoName = project.split('/')
        else:
            giturl = giturlparse(sourcestamps[0]['repository'])
            repoOwner = giturl.owner
            repoName = giturl.repo

        if self.verbose:
            log.msg(
                "Updating github status: repoOwner={repoOwner}, repoName={repoName}"
                .format(repoOwner=repoOwner, repoName=repoName))

        for sourcestamp in sourcestamps:
            if sourcestamp['revision'] != '':
                sha = sourcestamp['revision']
            else:
                try:
                    repo_user = repoOwner
                    repo_name = repoName
                    branch = sourcestamp['branch']
                    response = yield self.getSha(repo_user=repo_user,
                                                 repo_name=repo_name,
                                                 branch=branch)
                    content = yield response.content()
                    info = ast.literal_eval(content)
                    sha = info["object"]["sha"]
                except Exception as e:
                    sha = ''
                    log.err(
                        e, 'Failed to get sha for {repoOwner}/{repoName} '
                        'branch "{branch}"'
                        'http {code}, {content}'.format(repoOwner=repoOwner,
                                                        repoName=repoName,
                                                        branch=branch,
                                                        code=response.code,
                                                        content=content))
            try:
                repo_user = repoOwner
                repo_name = repoName
                sha = sha
                state = state
                target_url = build['url']
                context = context
                issue = issue
                description = description
                response = yield self.createStatus(repo_user=repo_user,
                                                   repo_name=repo_name,
                                                   sha=sha,
                                                   state=state,
                                                   target_url=target_url,
                                                   context=context,
                                                   issue=issue,
                                                   description=description)

                if not self.isStatus2XX(response.code):
                    raise Exception()

                if self.verbose:
                    log.msg(
                        'Updated status with "{state}" for {repoOwner}/{repoName} '
                        'at {sha}, context "{context}", issue {issue}.'.format(
                            state=state,
                            repoOwner=repoOwner,
                            repoName=repoName,
                            sha=sha,
                            issue=issue,
                            context=context))
            except Exception as e:
                content = yield response.content()
                log.err(
                    e, 'Failed to update "{state}" for {repoOwner}/{repoName} '
                    'at {sha}, context "{context}", issue {issue}. '
                    'http {code}, {content}'.format(state=state,
                                                    repoOwner=repoOwner,
                                                    repoName=repoName,
                                                    sha=sha,
                                                    issue=issue,
                                                    context=context,
                                                    code=response.code,
                                                    content=content))