Add latest release downloads sensor to GitHub (#183679)

This commit is contained in:
Yoav Mor
2026-09-30 08:45:01 +02:00
committed by GitHub
parent 3acd50a3ec
commit 0a0cb4fa16
8 changed files with 100 additions and 1 deletions
@@ -88,6 +88,11 @@ query ($owner: String!, $repository: String!) {
name
url
tag: tagName
assets: releaseAssets(first: 100) {
nodes {
download_count: downloadCount
}
}
}
refs(
first: 1
@@ -31,6 +31,9 @@
"latest_release": {
"default": "mdi:github"
},
"latest_release_downloads": {
"default": "mdi:download"
},
"latest_tag": {
"default": "mdi:tag"
},
+10
View File
@@ -86,6 +86,16 @@ SENSOR_DESCRIPTIONS: tuple[GitHubSensorEntityDescription, ...] = (
state_class=SensorStateClass.TOTAL,
value_fn=lambda data: data["merged_pull_request"]["total"],
),
GitHubSensorEntityDescription(
key="latest_release_downloads",
translation_key="latest_release_downloads",
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
avabl_fn=lambda data: data["release"] and data["release"]["assets"]["nodes"],
value_fn=lambda data: sum(
asset["download_count"] for asset in data["release"]["assets"]["nodes"]
),
),
GitHubSensorEntityDescription(
key="latest_commit",
translation_key="latest_commit",
@@ -67,6 +67,10 @@
"latest_release": {
"name": "Latest release"
},
"latest_release_downloads": {
"name": "Latest release downloads",
"unit_of_measurement": "downloads"
},
"latest_tag": {
"name": "Latest tag"
},
@@ -55,7 +55,8 @@
"release": {
"name": "v1.0.0",
"url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
"tag": "v1.0.0"
"tag": "v1.0.0",
"assets": { "nodes": [{ "download_count": 42 }] }
},
"refs": {
"tags": [
@@ -65,6 +65,13 @@
]),
}),
'release': dict({
'assets': dict({
'nodes': list([
dict({
'download_count': 42,
}),
]),
}),
'name': 'v1.0.0',
'tag': 'v1.0.0',
'url': 'https://github.com/octocat/Hello-World/releases/v1.0.0',
@@ -537,6 +537,61 @@
'state': 'v1.0.0',
})
# ---
# name: test_all_entities[sensor.octocat_hello_world_latest_release_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.octocat_hello_world_latest_release_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Latest release downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Latest release downloads',
'platform': 'github',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'latest_release_downloads',
'unique_id': '1296269_latest_release_downloads',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_all_entities[sensor.octocat_hello_world_latest_release_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.ATTRIBUTION: 'attribution'>: 'Data provided by the GitHub API',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'octocat/Hello-World Latest release downloads',
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.octocat_hello_world_latest_release_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '42',
})
# ---
# name: test_all_entities[sensor.octocat_hello_world_latest_tag-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
+14
View File
@@ -51,3 +51,17 @@ async def test_sensor_updates_with_empty_release_array(
new_state = hass.states.get(TEST_SENSOR_ENTITY)
assert new_state.state == STATE_UNAVAILABLE
async def test_latest_release_downloads_without_assets(
hass: HomeAssistant,
github_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the downloads sensor is unavailable when the release has no assets."""
release = github_client.graphql.return_value.data["data"]["repository"]["release"]
release["assets"]["nodes"] = []
await setup_integration(hass, mock_config_entry)
state = hass.states.get("sensor.octocat_hello_world_latest_release_downloads")
assert state.state == STATE_UNAVAILABLE