diff --git a/bumblebee_status/modules/contrib/gitlab.py b/bumblebee_status/modules/contrib/gitlab.py new file mode 100644 index 0000000..126650d --- /dev/null +++ b/bumblebee_status/modules/contrib/gitlab.py @@ -0,0 +1,78 @@ +# pylint: disable=C0111,R0903 + +""" +Displays the GitLab todo count: + + * https://docs.gitlab.com/ee/user/todos.html + * https://docs.gitlab.com/ee/api/todos.html + +Uses `xdg-open` or `x-www-browser` to open web-pages. + +Requires the following library: + * requests + +Errors: + if the GitLab todo query failed, the shown value is `n/a` + +Parameters: + * gitlab.token: GitLab personal access token, the token needs to have the "read_api" scope. + * gitlab.host: Host of the GitLab instance, default is "gitlab.com". + * gitlab.actions: Comma separated actions to be parsed (e.g.: gitlab.actions=assigned,approval_required) +""" + +import json +import requests +import shutil +import util + +import core.module +import core.widget +import core.decorators +import core.input + + +class Module(core.module.Module): + @core.decorators.every(minutes=5) + def __init__(self, config, theme): + super().__init__(config, theme, core.widget.Widget(self.gitlab)) + + self.background = True + self.__label = "" + self.__host = self.parameter("host", "gitlab.com") + + self.__actions = [] + actions = self.parameter("actions", "") + if actions: + self.__actions = util.format.aslist(actions) + + self.__requests = requests.Session() + self.__requests.headers.update({"PRIVATE-TOKEN": self.parameter("token", "")}) + + cmd = "xdg-open" + if not shutil.which(cmd): + cmd = "x-www-browser" + + core.input.register( + self, + button=core.input.LEFT_MOUSE, + cmd="{cmd} https:/{host}//dashboard/todos".format( + cmd=cmd, host=self.__host + ), + ) + + def gitlab(self, _): + return self.__label + + def update(self): + try: + url = "https://{host}/api/v4/todos".format(host=self.__host) + response = self.__requests.get(url) + todos = response.json() + if self.__actions: + todos = [t for t in todos if t["action_name"] in self.__actions] + self.__label = str(len(todos)) + except Exception as e: + self.__label = "n/a" + + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/requirements/modules/gitlab.txt b/requirements/modules/gitlab.txt new file mode 100644 index 0000000..f229360 --- /dev/null +++ b/requirements/modules/gitlab.txt @@ -0,0 +1 @@ +requests diff --git a/screenshots/gitlab.png b/screenshots/gitlab.png new file mode 100644 index 0000000..d488db0 Binary files /dev/null and b/screenshots/gitlab.png differ diff --git a/tests/modules/contrib/test_gitlab.py b/tests/modules/contrib/test_gitlab.py new file mode 100644 index 0000000..d3a3b9a --- /dev/null +++ b/tests/modules/contrib/test_gitlab.py @@ -0,0 +1,42 @@ +import pytest +from unittest import TestCase, mock + +import core.config +import core.widget +import modules.contrib.gitlab + +from requests import Session +from requests.models import Response + +pytest.importorskip("requests") + + +def build_gitlab_module(actions=""): + config = core.config.Config(["-p", "gitlab.actions={}".format(actions)]) + return modules.contrib.gitlab.Module(config=config, theme=None) + +def mock_todo_api_response(): + res = mock.Mock() + res.json = lambda: [ + {"action_name": "assigned"}, + {"action_name": "assigned"}, + {"action_name": "approval_required"}, + ] + res.status_code = 200 + return res + +class TestGitlabUnit(TestCase): + def test_load_module(self): + __import__("modules.contrib.gitlab") + + @mock.patch.object(Session, "get", return_value=mock_todo_api_response()) + def test_unfiltered(self, _): + module = build_gitlab_module() + module.update() + assert module.widgets()[0].full_text() == "3" + + @mock.patch.object(Session, "get", return_value=mock_todo_api_response()) + def test_filtered(self, _): + module = build_gitlab_module(actions="approval_required") + module.update() + assert module.widgets()[0].full_text() == "1" diff --git a/themes/icons/ascii.json b/themes/icons/ascii.json index 089fa3c..d353386 100644 --- a/themes/icons/ascii.json +++ b/themes/icons/ascii.json @@ -309,6 +309,9 @@ "github": { "prefix": "github" }, + "gitlab": { + "prefix": "gitlab" + }, "deezer": { "prefix": "" }, diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json index e3aeebe..4015e43 100644 --- a/themes/icons/awesome-fonts.json +++ b/themes/icons/awesome-fonts.json @@ -581,6 +581,9 @@ "github": { "prefix": "  " }, + "gitlab": { + "prefix": "" + }, "deezer": { "prefix": "  " },