core/homeassistant/components/gitlab_ci/sensor.py

181 lines
5.7 KiB
Python

"""Sensor for retrieving latest GitLab CI job information."""
from datetime import timedelta
import logging
from gitlab import Gitlab, GitlabAuthenticationError, GitlabGetError
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.const import (
ATTR_ATTRIBUTION,
CONF_NAME,
CONF_SCAN_INTERVAL,
CONF_TOKEN,
CONF_URL,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
ATTR_BUILD_BRANCH = "build branch"
ATTR_BUILD_COMMIT_DATE = "commit date"
ATTR_BUILD_COMMIT_ID = "commit id"
ATTR_BUILD_DURATION = "build_duration"
ATTR_BUILD_FINISHED = "build_finished"
ATTR_BUILD_ID = "build id"
ATTR_BUILD_STARTED = "build_started"
ATTR_BUILD_STATUS = "build_status"
ATTRIBUTION = "Information provided by https://gitlab.com/"
CONF_GITLAB_ID = "gitlab_id"
DEFAULT_NAME = "GitLab CI Status"
DEFAULT_URL = "https://gitlab.com"
ICON_HAPPY = "mdi:emoticon-happy"
ICON_OTHER = "mdi:git"
ICON_SAD = "mdi:emoticon-sad"
SCAN_INTERVAL = timedelta(seconds=300)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_GITLAB_ID): cv.string,
vol.Required(CONF_TOKEN): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_URL, default=DEFAULT_URL): cv.string,
}
)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the GitLab sensor platform."""
_name = config.get(CONF_NAME)
_interval = config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL)
_url = config.get(CONF_URL)
_gitlab_data = GitLabData(
priv_token=config[CONF_TOKEN],
gitlab_id=config[CONF_GITLAB_ID],
interval=_interval,
url=_url,
)
add_entities([GitLabSensor(_gitlab_data, _name)], True)
class GitLabSensor(SensorEntity):
"""Representation of a GitLab sensor."""
def __init__(self, gitlab_data, name):
"""Initialize the GitLab sensor."""
self._available = False
self._state = None
self._started_at = None
self._finished_at = None
self._duration = None
self._commit_id = None
self._commit_date = None
self._build_id = None
self._branch = None
self._gitlab_data = gitlab_data
self._name = name
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def native_value(self):
"""Return the state of the sensor."""
return self._state
@property
def available(self):
"""Return True if entity is available."""
return self._available
@property
def extra_state_attributes(self):
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: ATTRIBUTION,
ATTR_BUILD_STATUS: self._state,
ATTR_BUILD_STARTED: self._started_at,
ATTR_BUILD_FINISHED: self._finished_at,
ATTR_BUILD_DURATION: self._duration,
ATTR_BUILD_COMMIT_ID: self._commit_id,
ATTR_BUILD_COMMIT_DATE: self._commit_date,
ATTR_BUILD_ID: self._build_id,
ATTR_BUILD_BRANCH: self._branch,
}
@property
def icon(self):
"""Return the icon to use in the frontend."""
if self._state == "success":
return ICON_HAPPY
if self._state == "failed":
return ICON_SAD
return ICON_OTHER
def update(self):
"""Collect updated data from GitLab API."""
self._gitlab_data.update()
self._state = self._gitlab_data.status
self._started_at = self._gitlab_data.started_at
self._finished_at = self._gitlab_data.finished_at
self._duration = self._gitlab_data.duration
self._commit_id = self._gitlab_data.commit_id
self._commit_date = self._gitlab_data.commit_date
self._build_id = self._gitlab_data.build_id
self._branch = self._gitlab_data.branch
self._available = self._gitlab_data.available
class GitLabData:
"""GitLab Data object."""
def __init__(self, gitlab_id, priv_token, interval, url):
"""Fetch data from GitLab API for most recent CI job."""
self._gitlab_id = gitlab_id
self._gitlab = Gitlab(url, private_token=priv_token, per_page=1)
self._gitlab.auth()
self.update = Throttle(interval)(self._update)
self.available = False
self.status = None
self.started_at = None
self.finished_at = None
self.duration = None
self.commit_id = None
self.commit_date = None
self.build_id = None
self.branch = None
def _update(self):
try:
_projects = self._gitlab.projects.get(self._gitlab_id)
_last_pipeline = _projects.pipelines.list(page=1)[0]
_last_job = _last_pipeline.jobs.list(page=1)[0]
self.status = _last_pipeline.attributes.get("status")
self.started_at = _last_job.attributes.get("started_at")
self.finished_at = _last_job.attributes.get("finished_at")
self.duration = _last_job.attributes.get("duration")
_commit = _last_job.attributes.get("commit")
self.commit_id = _commit.get("id")
self.commit_date = _commit.get("committed_date")
self.build_id = _last_job.attributes.get("id")
self.branch = _last_job.attributes.get("ref")
self.available = True
except GitlabAuthenticationError as erra:
_LOGGER.error("Authentication Error: %s", erra)
self.available = False
except GitlabGetError as errg:
_LOGGER.error("Project Not Found: %s", errg)
self.available = False