コード例 #1
0
ファイル: build_test.py プロジェクト: ruleant/buildtime-trend
    def test_load_properties(self):
        self.build.load_properties_from_settings()

        self.assertDictEqual(
            {'duration': 0, "repo": buildtimetrend.NAME},
            self.build.get_properties())

        settings = Settings()
        settings.add_setting("ci_platform", "travis")
        settings.add_setting("build", "123")
        settings.add_setting("job", "123.1")
        settings.add_setting("branch", "branch1")
        settings.add_setting("result", "passed")
        settings.set_project_name("test/project")

        self.build.load_properties_from_settings()
        self.assertDictEqual(
            {   'duration': 0,
                'ci_platform': "travis",
                'build': "123",
                'job': "123.1",
                'branch': "branch1",
                'result': "passed",
                'repo': "test/project"},
            self.build.get_properties())
コード例 #2
0
ファイル: tools.py プロジェクト: buildtimetrend/python-lib
def process_notification_payload(payload):
    """
    Extract repo slug and build number from Travis notification payload.

    Returns a dictionary with "repo" and "build" information,
    or an empty dictionary if the payload could not be processed.

    Deprecated behaviour : Currently the repo and build information are
    also stored in the "settings" object,
    but this will be removed in the near future.

    Parameters:
    - payload : Travis CI notification payload
    """
    settings = Settings()
    parameters = {}

    if payload is None:
        logger.warning("Travis notification payload is not set")
        return parameters

    if not is_string(payload):
        logger.warning(
            "Travis notification payload is incorrect :"
            " string expected, got %s", type(payload))
        return parameters

    json_payload = json.loads(payload)
    logger.info("Travis Payload : %r.", json_payload)

    # get repo name from payload
    if ("repository" in json_payload
            and "owner_name" in json_payload["repository"]
            and "name" in json_payload["repository"]):

        repo = get_repo_slug(json_payload["repository"]["owner_name"],
                             json_payload["repository"]["name"])

        logger.info("Build repo : %s", repo)
        settings.set_project_name(repo)
        parameters["repo"] = repo

    # get build number from payload
    if "number" in json_payload:
        logger.info("Build number : %s", str(json_payload["number"]))
        settings.add_setting('build', json_payload['number'])
        parameters["build"] = json_payload['number']

    return parameters
コード例 #3
0
ファイル: travis.py プロジェクト: ruleant/buildtime-trend
def load_travis_env_vars():
    '''
    Loads Travis CI environment variables and assigns them to
    the corresponding settings item.
    '''
    if "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true":
        settings = Settings()

        # set ci_platform setting to "travis"
        settings.add_setting("ci_platform", "travis")

        # set settings with TRAVIS values
        env_var_to_settings("TRAVIS_BUILD_NUMBER", "build")
        env_var_to_settings("TRAVIS_JOB_NUMBER", "job")
        env_var_to_settings("TRAVIS_BRANCH", "branch")
        env_var_to_settings("TRAVIS_REPO_SLUG", "project_name")

        # convert and set Travis build result
        if "TRAVIS_TEST_RESULT" in os.environ:
            # map $TRAVIS_TEST_RESULT to a more readable value
            settings.add_setting(
                "result",
                convert_build_result(os.environ["TRAVIS_TEST_RESULT"])
            )
コード例 #4
0
    def test_load_properties(self):
        """Test loading properties"""
        self.build.load_properties_from_settings()

        self.assertDictEqual(
            {'duration': 0, "repo": buildtimetrend.NAME},
            self.build.get_properties())

        settings = Settings()
        settings.add_setting("ci_platform", "travis")
        settings.add_setting("build", "123")
        settings.add_setting("job", "123.1")
        settings.add_setting("branch", "branch1")
        settings.add_setting("result", "passed")
        settings.add_setting("build_trigger", "push")
        settings.add_setting(
            "pull_request",
            {
                "is_pull_request": False,
                "title": None,
                "number": None
            }
        )
        settings.set_project_name("test/project")

        self.build.load_properties_from_settings()
        self.assertDictEqual(
            {
                'duration': 0,
                'ci_platform': "travis",
                'build': "123",
                'job': "123.1",
                'branch': "branch1",
                'result': "passed",
                'build_trigger': "push",
                'pull_request': {
                    "is_pull_request": False,
                    "title": None,
                    "number": None},
                'repo': "test/project"
            },
            self.build.get_properties())
コード例 #5
0
class TravisParser(object):
    """
    Travis CI build timing and build data parser.

    Retrieve timing data from Travis CI, parse it and store it in Keen.io.
    """
    def __init__(self):
        """Initialise class."""
        self.settings = Settings()

        # get logger
        self.logger = logger

    @cherrypy.expose
    def default(self,
                repo_owner=None,
                repo_name=None,
                first_build=None,
                last_build=None,
                payload=None):
        """
        Default handler.

        Visiting this page triggers loading and processing the build log
        and data of a travis CI build process.

        If last_build is defined, all builds from first_build until last_build
        will be retrieved and processed.

        If only payload is defined, repo and build data
        will be extracted from the payload.

        Parameters:
        - repo_owner : name of the Github repo owner, fe. `buildtimetrend`
        - repo_name : name of the Github repo, fe. `service`
        - first_build : first build number to process (int)
        - last_build : last build number to process (int)
        - payload : Travis CI notification payload (json)
        """
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        # reset settings
        self.settings.set_project_name(None)
        self.settings.add_setting('build', None)

        self.logger.debug("Check Travis headers : %r",
                          cherrypy.request.headers)

        repo = get_repo_slug(repo_owner, repo_name)

        # load parameters from the Travis notification payload
        if self.check_travis_notification():
            payload_params = process_notification_payload(payload)

            # assign payload parameters
            if repo is None and "repo" in payload_params:
                repo = payload_params["repo"]
            if first_build is None and last_build is None and \
                    "build" in payload_params:
                first_build = payload_params["build"]

        # check parameter validity, check returns error message
        # or None if parameters are valid
        params_valid = validate_travis_request(repo, first_build)
        if params_valid is not None:
            self.logger.warning(params_valid)
            return params_valid

        if last_build is None:
            self.logger.warning("Request to process build #%s of repo %s",
                                first_build, repo)

            # schedule task with 10 second delay to give Travis CI time
            # to add the finished_at property. (issue #96)
            return self.schedule_task(repo, first_build, 10)

        return self.multi_build(repo, first_build, last_build)

    def multi_build(self, repo, first_build, last_build):
        """
        Schedule processing multiple consecutive builds.

        All builds from first_build until last_build
        will be retrieved and processed.

        The total number of builds to be scheduled is limited by the
        `multi_import.max_builds` config parameter.

        Every next scheduled build will be delayed by the
        `multi_import.delay` config parameter.

        Parameters:
        - repo : repo name (fe. buildtimetrend/service)
        - first_build : first build number to process (int)
        - last_build : last build number to process (int)
        """
        first_build = int(first_build)
        last_build = int(last_build)
        message = ""
        multi_import = Settings().get_setting("multi_import")
        max_multi_builds = int(multi_import["max_builds"])

        if last_build < first_build:
            tmp_msg = "Warning : last_build should be equal" \
                " or larger than first_build"
            self.logger.warning(tmp_msg)
            message += tmp_msg + "\n"
            last_build = first_build

        if (last_build - first_build) > max_multi_builds:
            tmp_msg = "Warning : number of multiple builds is limited to {:d}"
            self.logger.warning(tmp_msg.format(max_multi_builds))
            message += tmp_msg.format(max_multi_builds) + "\n"
            last_build = first_build + max_multi_builds

        message += "Request to process build(s) #{first_build:d} to" \
            " #{last_build:d} of repo {repo}:\n".format(**locals())

        build = first_build
        delay = 0

        while build <= last_build:
            message += self.schedule_task(repo, build, delay) + "\n"
            delay += multi_import["delay"]
            build += 1

        return message

    def schedule_task(self, repo, build, delay=0):
        """
        Schedule task.

        Parameters:
        - repo : repo name (fe. buildtimetrend/service)
        - build : build number to process (int)
        - delay : delay before task should be started, in seconds
        """
        # process travis build
        if is_worker_enabled():
            task = tasks.process_travis_buildlog.apply_async(
                (repo, build), countdown=int(delay))
            temp_msg = "Task scheduled to process build #{build}" \
                " of repo {repo} : {task_id}"
            self.logger.warning(
                temp_msg.format(build=build, repo=repo, task_id=task.id))
            return temp_msg.format(build=cgi.escape(str(build)),
                                   repo=cgi.escape(str(repo)),
                                   task_id=cgi.escape(str(task.id)))
        else:
            return tasks.process_travis_buildlog(repo, build)

    def check_travis_notification(self):
        """
        Check Travis CI notification request.

        Load Authorization and Travis-Repo-Slug headers and check if
        the Authorization header is correct
        """
        if "Authorization" not in cherrypy.request.headers:
            self.logger.debug("Authorization header is not set")
            return True

        if "Travis-Repo-Slug" not in cherrypy.request.headers:
            self.logger.debug("Travis-Repo-Slug header is not set")
            return False

        return check_authorization(
            cherrypy.request.headers["Travis-Repo-Slug"],
            cherrypy.request.headers["Authorization"])
コード例 #6
0
class TestSettings(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        self.settings = Settings()

        self.project_name = buildtimetrend.NAME

        self.project_info = {
            "version": buildtimetrend.VERSION,
            "schema_version": buildtimetrend.SCHEMA_VERSION,
            "project_name": self.project_name}

    def setUp(self):
        # reinit settings singleton
        if self.settings is not None:
            self.settings.__init__()

    def test_get_project_info(self):
        self.assertDictEqual(self.project_info, self.settings.get_project_info())

    def test_get_set_project_name(self):
        self.assertEquals(self.project_name, self.settings.get_project_name())

        self.settings.set_project_name("test_name")
        self.assertEquals("test_name", self.settings.get_project_name())

        self.settings.set_project_name(None)
        self.assertEquals(None, self.settings.get_project_name())

        self.settings.set_project_name("")
        self.assertEquals("", self.settings.get_project_name())

    def test_get_add_setting(self):
        # setting is not set yet
        self.assertEquals(None, self.settings.get_setting("test_name"))

        self.settings.add_setting("test_name", "test_value")
        self.assertEquals("test_value", self.settings.get_setting("test_name"))

        self.settings.add_setting("test_name", None)
        self.assertEquals(None, self.settings.get_setting("test_name"))

        self.settings.add_setting("test_name", "")
        self.assertEquals("", self.settings.get_setting("test_name"))

        self.settings.add_setting("test_name", 6)
        self.assertEquals(6, self.settings.get_setting("test_name"))

    def test_get_setting(self):
        self.assertEquals(None, self.settings.get_setting("test_name"))

        self.assertEquals(
            self.project_name,
            self.settings.get_setting("project_name"))

        self.assertDictEqual(
            {
                "project_name": self.project_name,
                "mode_native": False,
                "mode_keen": True
            },
            self.settings.settings.get_items())

    def test_no_config_file(self):
        # function should return false when file doesn't exist
        self.assertFalse(self.settings.load_config_file('no_file.yml'))
        self.assertDictEqual(
            {
                "project_name": self.project_name,
                "mode_native": False,
                "mode_keen": True
            },
            self.settings.settings.get_items())

        self.assertFalse(self.settings.load_config_file(''))
        self.assertDictEqual(
            {
                "project_name": self.project_name,
                "mode_native": False,
                "mode_keen": True
            },
            self.settings.settings.get_items())

        # function should throw an error when no filename is set
        self.assertRaises(TypeError, self.settings.load_config_file)

    def test_load_config_file(self):
        # checking if Keen.io configuration is not set (yet)
        self.assertEquals(None, keen.project_id)
        self.assertEquals(None, keen.write_key)
        self.assertEquals(None, keen.read_key)

        # load sample config file
        self.assertTrue(self.settings.load_config_file(constants.TEST_SAMPLE_CONFIG_FILE))
        self.assertDictEqual(
            {"project_name": "test_project",
            "mode_native": True,
            "mode_keen": False,
            "setting1": "test_value1"},
            self.settings.settings.get_items())

        # checking if Keen.io configuration is set
        self.assertEquals("1234", keen.project_id)
        self.assertEquals("12345678", keen.write_key)
        self.assertEquals("abcdefg", keen.read_key)
        self.assertTrue(keen_is_readable())
        self.assertTrue(keen_is_writable())
コード例 #7
0
    def test_load_properties(self):
        """Test loading properties"""
        self.build.load_properties_from_settings()

        self.assertDictEqual({
            'duration': 0,
            "repo": buildtimetrend.NAME
        }, self.build.get_properties())

        settings = Settings()
        settings.add_setting("ci_platform", "travis")
        settings.add_setting("build", "123")
        settings.add_setting("job", "123.1")
        settings.add_setting("branch", "branch1")
        settings.add_setting("result", "passed")
        settings.add_setting("build_trigger", "push")
        settings.add_setting("pull_request", {
            "is_pull_request": False,
            "title": None,
            "number": None
        })
        settings.set_project_name("test/project")

        self.build.load_properties_from_settings()
        self.assertDictEqual(
            {
                'duration': 0,
                'ci_platform': "travis",
                'build': "123",
                'job': "123.1",
                'branch': "branch1",
                'result': "passed",
                'build_trigger': "push",
                'pull_request': {
                    "is_pull_request": False,
                    "title": None,
                    "number": None
                },
                'repo': "test/project"
            }, self.build.get_properties())