updates2mqtt 1.4.1__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. updates2mqtt-1.5.0/.github/workflows/auto_assign_issue.yml +18 -0
  2. updates2mqtt-1.5.0/.github/workflows/auto_assign_pr.yml +18 -0
  3. updates2mqtt-1.5.0/.github/workflows/main.yml +18 -0
  4. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.pre-commit-config.yaml +2 -2
  5. updates2mqtt-1.5.0/CHANGELOG.md +36 -0
  6. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/PKG-INFO +13 -6
  7. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/README.md +12 -5
  8. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/common_packages.yaml +38 -3
  9. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/conftest.py +1 -1
  10. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/examples/config_maximal.md +1 -1
  11. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/examples/config_minimal.md +1 -1
  12. updates2mqtt-1.5.0/docs/examples/docker_compose.md +9 -0
  13. updates2mqtt-1.5.0/docs/examples/env.md +7 -0
  14. updates2mqtt-1.5.0/docs/examples/index.md +5 -0
  15. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/home_assistant.md +20 -3
  16. updates2mqtt-1.5.0/docs/images/updates2mqtt-dark-256x256.png +0 -0
  17. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/installation.md +6 -5
  18. updates2mqtt-1.5.0/docs/robots.txt +4 -0
  19. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/troubleshooting.md +8 -0
  20. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/examples/config.yaml.maximal +3 -0
  21. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/examples/docker-compose.yaml +1 -1
  22. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/mkdocs.yml +21 -3
  23. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/pyproject.toml +4 -2
  24. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/scripts/healthcheck.sh +5 -0
  25. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/app.py +16 -9
  26. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/config.py +26 -6
  27. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/hass_formatter.py +34 -11
  28. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/integrations/docker.py +54 -19
  29. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/mqtt.py +26 -18
  30. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/test_config.py +9 -3
  31. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/test_docker.py +4 -4
  32. updates2mqtt-1.5.0/tests/test_hass_formatter.py +85 -0
  33. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/test_mqtt.py +4 -4
  34. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/uv.lock +144 -45
  35. updates2mqtt-1.4.1/CHANGELOG.md +0 -22
  36. updates2mqtt-1.4.1/docs/examples/docker_compose.md +0 -7
  37. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.dockerignore +0 -0
  38. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.github/dependabot.yml +0 -0
  39. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.github/workflows/docker-publish.yml +0 -0
  40. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.github/workflows/pypi-publish.yml +0 -0
  41. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.github/workflows/python-package.yml +0 -0
  42. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.gitignore +0 -0
  43. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.hintrc +0 -0
  44. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.python-version +0 -0
  45. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/.safety-project.ini +0 -0
  46. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/Dockerfile +0 -0
  47. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/LICENSE +0 -0
  48. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/SECURITY.md +0 -0
  49. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/configuration.md +0 -0
  50. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/ha_entities.png +0 -0
  51. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/ha_mqtt_discovery.png +0 -0
  52. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/ha_update_detail.png +0 -0
  53. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/ha_update_dialog.png +0 -0
  54. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/ha_update_page.png +0 -0
  55. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/images/logo-blank-256x256.png +0 -0
  56. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/index.md +0 -0
  57. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/docs/local_builds.md +0 -0
  58. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/examples/config.yaml.minimal +0 -0
  59. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/no_config.yaml +0 -0
  60. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/refresh-deps.sh +0 -0
  61. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/__init__.py +0 -0
  62. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/__main__.py +0 -0
  63. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/integrations/__init__.py +0 -0
  64. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/integrations/git_utils.py +0 -0
  65. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/model.py +0 -0
  66. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/src/updates2mqtt/py.typed +0 -0
  67. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/__init__.py +0 -0
  68. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/test_app.py +0 -0
  69. {updates2mqtt-1.4.1 → updates2mqtt-1.5.0}/tests/test_git_utils.py +0 -0
@@ -0,0 +1,18 @@
1
+ name: Issue assignment
2
+
3
+ on:
4
+ issues:
5
+ types: [opened]
6
+
7
+ jobs:
8
+ auto-assign:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ issues: write
12
+ steps:
13
+ - name: 'Auto-assign issue'
14
+ uses: pozil/auto-assign-issue@39c06395cbac76e79afc4ad4e5c5c6db6ecfdd2e
15
+ with:
16
+ assignees: jeyrb
17
+ numOfAssignee: 1
18
+ allowSelfAssign: true
@@ -0,0 +1,18 @@
1
+ name: PR assignment
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, edited, synchronize, reopened]
6
+
7
+ jobs:
8
+ auto-assign:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ pull-requests: write
12
+ steps:
13
+ - name: 'Auto-assign PR'
14
+ uses: pozil/auto-assign-issue@39c06395cbac76e79afc4ad4e5c5c6db6ecfdd2e
15
+ with:
16
+ repo-token: ${{ secrets.MY_PERSONAL_ACCESS_TOKEN }}
17
+ assignees: jeyrb
18
+ numOfAssignee: 1
@@ -0,0 +1,18 @@
1
+ name: Issue assignment
2
+
3
+ on:
4
+ issues:
5
+ types: [opened]
6
+
7
+ jobs:
8
+ auto-assign:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ issues: write
12
+ steps:
13
+ - name: 'Auto-assign issue'
14
+ uses: pozil/auto-assign-issue@v2
15
+ with:
16
+ assignees: jeyrb
17
+ numOfAssignee: 1
18
+ allowSelfAssign: true
@@ -17,11 +17,11 @@ repos:
17
17
  - id: check-shebang-scripts-are-executable
18
18
  name: Check shell scripts are executable
19
19
  - repo: https://github.com/astral-sh/uv-pre-commit
20
- rev: 0.9.13
20
+ rev: 0.9.16
21
21
  hooks:
22
22
  - id: uv-lock
23
23
  - repo: https://github.com/astral-sh/ruff-pre-commit
24
- rev: v0.14.7
24
+ rev: v0.14.8
25
25
  hooks:
26
26
  # Run the linter.
27
27
  - id: ruff-check
@@ -0,0 +1,36 @@
1
+ # CHANGELOG
2
+
3
+ ## 1.5.0
4
+ - Target specific service on docker compose commands, where available from `com.docker.compose.service` label
5
+ - Log level in config is now an enum, and forced to be upper case
6
+ - Removed unnecessary latest_version fields from config message, which also saves a redundant MQTT subscription
7
+ - Publication of `command_topic` for each discovery can now be forced with `force_command_topic` option
8
+ - More common packages: docker:cli
9
+ - Common packages can now match on the image ref rather than base name, for example `docker:cli`
10
+ - Reduced log noise in INFO and increased logging detail for DEBUG
11
+ - Common Packages now allow entries without all the values, initially `rtl_433` which lacks a logo
12
+ ## 1.4.2
13
+ - Replace `origin` in config MQTT message with `device` for better HomeAssistant compatibility
14
+ - An `area` can be defined in the Home Assistant section of config and this will then be used as `suggested_area` for device
15
+ - Icon and release note info added for Owntone, Nextcloud, n8n, and Homarr
16
+ - More testcases
17
+ ## 1.4.1
18
+ - More logging for Docker discovery on why Home Assistant doesn't show an update button
19
+ - More test cases
20
+ - `MqttClient` is now `MqttPublisher` to avoid confusion with actual MQTT client
21
+ - Task cleanup now only interrupts explicit list of tasks - healthcheck and discovery tasks
22
+ ## 1.4.0
23
+ - MQTT protocol can now be set, to one of `3.1`,`3.11` or `5`
24
+ - Debug messages now provided for `on_subscribe` and `on_unsubscribe` callbacks
25
+ - Troubleshooting, installation, configuration docs updated, images optimized
26
+
27
+ ## 1.3.7
28
+ - Improved initial setup when run without config or env vars for MQTT
29
+ - Minor test deps update and pyproject docs
30
+
31
+ ## 1.3.6
32
+ - Changed exit code on graceful shutdown to 143
33
+ - App now exits if the MQTT username / password is not authorized
34
+ - Improved handling of env vars, default config now assumes MQTT_HOST etc unless overridden
35
+ - Will now run without a config if correct `MQTT_HOST`,`MQTT_USER`,`MQTT_PASS`,`MQTT_PORT` env vars set or match the defaults (`127.0.0.1:1883`)
36
+ - Deps update
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: updates2mqtt
3
- Version: 1.4.1
3
+ Version: 1.5.0
4
4
  Summary: System update and docker image notification and execution over MQTT
5
5
  Project-URL: Homepage, https://updates2mqtt.rhizomatics.org.uk
6
6
  Project-URL: Repository, https://github.com/rhizomatics/updates2mqtt
@@ -35,7 +35,7 @@ Requires-Dist: structlog>=25.4.0
35
35
  Requires-Dist: usingversion>=0.1.2
36
36
  Description-Content-Type: text/markdown
37
37
 
38
- [![Rhizomatics Open Source](https://avatars.githubusercontent.com/u/162821163?s=96&v=4)](https://github.com/rhizomatics)
38
+ ![updates2mqtt](images/updates2mqtt-dark-256x256.png){ align=left }
39
39
 
40
40
  # updates2mqtt
41
41
 
@@ -43,14 +43,19 @@ Description-Content-Type: text/markdown
43
43
 
44
44
  [![PyPI - Version](https://img.shields.io/pypi/v/updates2mqtt)](https://pypi.org/project/updates2mqtt/)
45
45
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/rhizomatics/supernotify)
46
- ![Coverage](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/ff84fbfac358820cf9c9e9e582c063cd1a137116/badges/coverage.svg)
47
- ![Tests](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/ff84fbfac358820cf9c9e9e582c063cd1a137116/badges/tests.svg)
46
+ [![Coverage](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/refs/heads/badges/badges/coverage.svg)](https://updates2mqtt.rhizomatics.org.uk/developer/coverage/)
47
+ ![Tests](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/refs/heads/badges/badges/tests.svg)
48
48
  [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/rhizomatics/updates2mqtt/main.svg)](https://results.pre-commit.ci/latest/github/rhizomatics/updates2mqtt/main)
49
49
  [![Publish Python 🐍 distribution 📦 to PyPI and TestPyPI](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml)
50
50
  [![Github Deploy](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml/badge.svg?branch=main)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml)
51
51
  [![CodeQL](https://github.com/rhizomatics/updates2mqtt/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/github-code-scanning/codeql)
52
52
  [![Dependabot Updates](https://github.com/rhizomatics/updates2mqtt/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/dependabot/dependabot-updates)
53
53
 
54
+
55
+ <br/>
56
+ <br/>
57
+
58
+
54
59
  ## Summary
55
60
 
56
61
  Let Home Assistant tell you about new updates to Docker images for your containers.
@@ -86,15 +91,17 @@ Presently only Docker containers are supported, although others are planned, pro
86
91
  |-----------|-------------|----------------------------------------------------------------------------------------------------|
87
92
  | Docker | Scan. Fetch | Fetch is ``docker pull`` only. Restart support only for ``docker-compose`` image based containers. |
88
93
 
89
- ## Healthcheck
94
+ ## Heartbeat
90
95
 
91
96
  A heartbeat JSON payload is optionally published periodically to a configurable MQTT topic, defaulting to `healthcheck/{node_name}/updates2mqtt`. It contains the current version of updates2mqtt, the node name, a timestamp, and some basic stats.
92
97
 
98
+ ## Healthcheck
99
+
93
100
  A `healthcheck.sh` script is included in the Docker image, and can be used as a Docker healthcheck, if the container environment variables are set for `MQTT_HOST`, `MQTT_PORT`, `MQTT_USER` and `MQTT_PASS`. It uses the `mosquitto-clients` Linux package which provides `mosquitto_sub` command to subscribe to topics.
94
101
 
95
102
  !!! tip
96
103
 
97
- Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq`
104
+ Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq` (can omit `| jq` if you don't have jsonquery installed, but much easier to read with it)
98
105
 
99
106
  Another approach is using a restarter service directly in Docker Compose to force a restart, in this case once a day:
100
107
 
@@ -1,4 +1,4 @@
1
- [![Rhizomatics Open Source](https://avatars.githubusercontent.com/u/162821163?s=96&v=4)](https://github.com/rhizomatics)
1
+ ![updates2mqtt](images/updates2mqtt-dark-256x256.png){ align=left }
2
2
 
3
3
  # updates2mqtt
4
4
 
@@ -6,14 +6,19 @@
6
6
 
7
7
  [![PyPI - Version](https://img.shields.io/pypi/v/updates2mqtt)](https://pypi.org/project/updates2mqtt/)
8
8
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/rhizomatics/supernotify)
9
- ![Coverage](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/ff84fbfac358820cf9c9e9e582c063cd1a137116/badges/coverage.svg)
10
- ![Tests](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/ff84fbfac358820cf9c9e9e582c063cd1a137116/badges/tests.svg)
9
+ [![Coverage](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/refs/heads/badges/badges/coverage.svg)](https://updates2mqtt.rhizomatics.org.uk/developer/coverage/)
10
+ ![Tests](https://raw.githubusercontent.com/rhizomatics/updates2mqtt/refs/heads/badges/badges/tests.svg)
11
11
  [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/rhizomatics/updates2mqtt/main.svg)](https://results.pre-commit.ci/latest/github/rhizomatics/updates2mqtt/main)
12
12
  [![Publish Python 🐍 distribution 📦 to PyPI and TestPyPI](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml)
13
13
  [![Github Deploy](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml/badge.svg?branch=main)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml)
14
14
  [![CodeQL](https://github.com/rhizomatics/updates2mqtt/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/github-code-scanning/codeql)
15
15
  [![Dependabot Updates](https://github.com/rhizomatics/updates2mqtt/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/rhizomatics/updates2mqtt/actions/workflows/dependabot/dependabot-updates)
16
16
 
17
+
18
+ <br/>
19
+ <br/>
20
+
21
+
17
22
  ## Summary
18
23
 
19
24
  Let Home Assistant tell you about new updates to Docker images for your containers.
@@ -49,15 +54,17 @@ Presently only Docker containers are supported, although others are planned, pro
49
54
  |-----------|-------------|----------------------------------------------------------------------------------------------------|
50
55
  | Docker | Scan. Fetch | Fetch is ``docker pull`` only. Restart support only for ``docker-compose`` image based containers. |
51
56
 
52
- ## Healthcheck
57
+ ## Heartbeat
53
58
 
54
59
  A heartbeat JSON payload is optionally published periodically to a configurable MQTT topic, defaulting to `healthcheck/{node_name}/updates2mqtt`. It contains the current version of updates2mqtt, the node name, a timestamp, and some basic stats.
55
60
 
61
+ ## Healthcheck
62
+
56
63
  A `healthcheck.sh` script is included in the Docker image, and can be used as a Docker healthcheck, if the container environment variables are set for `MQTT_HOST`, `MQTT_PORT`, `MQTT_USER` and `MQTT_PASS`. It uses the `mosquitto-clients` Linux package which provides `mosquitto_sub` command to subscribe to topics.
57
64
 
58
65
  !!! tip
59
66
 
60
- Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq`
67
+ Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq` (can omit `| jq` if you don't have jsonquery installed, but much easier to read with it)
61
68
 
62
69
  Another approach is using a restarter service directly in Docker Compose to force a restart, in this case once a day:
63
70
 
@@ -3,7 +3,7 @@ common_packages:
3
3
  docker:
4
4
  image_name: ghcr.io/rhizomatics/updates2mqtt
5
5
  logo_url: https://avatars.githubusercontent.com/u/162821163?s=48&v=4
6
- release_notes_url: https://github.com/rhizomatics/updates2mqtt/pkgs/container/updates2mqtt
6
+ release_notes_url: https://github.com/rhizomatics/updates2mqtt/releases
7
7
 
8
8
  frigate:
9
9
  docker:
@@ -26,7 +26,7 @@ common_packages:
26
26
  caddy:
27
27
  docker:
28
28
  image_name: caddy
29
- logo_url: https://d1q6f0aelx0por.cloudfront.net/product-logos/library-caddy-logo.png
29
+ logo_url: https://avatars.githubusercontent.com/u/12955528?s=48&v=4
30
30
  release_notes_url: https://github.com/caddyserver/caddy/releases
31
31
 
32
32
  uptime-kuma:
@@ -81,4 +81,39 @@ common_packages:
81
81
  docker:
82
82
  image_name: jellyfin/jellyfin
83
83
  logo_url: https://avatars.githubusercontent.com/u/45698031?s=48&v=4
84
- release_notes_url: https://github.com/jellyfin/jellyfin/releases
84
+ release_notes_url: https://github.com/jellyfin/jellyfin/releases
85
+
86
+ owntone:
87
+ docker:
88
+ image_name: owntone/owntone
89
+ logo_url: https://raw.githubusercontent.com/owntone/owntone-server/443fb684871e005a7e442a08cc4d610208abbe6c/docs/assets/logo.svg
90
+ release_notes_url: https://github.com/owntone/owntone-server/releases
91
+
92
+ homarr:
93
+ docker:
94
+ image_name: ghcr.io/homarr-labs/homarr
95
+ logo_url: https://github.com/homarr-labs/homarr/blob/dev/docs/img/logo/2340450-2-title.png?raw=true
96
+ release_notes_url: https://github.com/homarr-labs/homarr/releases
97
+
98
+ nextcloud:
99
+ docker:
100
+ image_name: nextcloud
101
+ logo_url: https://avatars.githubusercontent.com/u/19211038?s=48&v=4
102
+ release_notes_url: https://github.com/nextcloud/docker/releases
103
+
104
+ n8n:
105
+ docker:
106
+ image_name: docker.n8n.io/n8nio/n8n
107
+ logo_url: https://avatars.githubusercontent.com/u/45487711?s=48&v=4
108
+ release_notes_url: https://github.com/n8n-io/n8n/releases
109
+
110
+ docker_cli:
111
+ docker:
112
+ image_name: docker:cli
113
+ logo_url: https://www.docker.com/app/uploads/2023/05/cli_1@2x.png
114
+ release_notes_url: https://github.com/docker-library/docker/commits/master/29/cli
115
+
116
+ rtl_433:
117
+ docker:
118
+ image_name: hertzg/rtl_433
119
+ release_notes_url: https://github.com/merbanan/rtl_433/releases
@@ -35,7 +35,7 @@ def app_with_mocked_external_dependencies(
35
35
 
36
36
  @pytest.fixture
37
37
  def mock_discoveries(mock_provider: ReleaseProvider) -> list[Discovery]:
38
- return [Discovery(mock_provider, "thing-1", "test001")]
38
+ return [Discovery(mock_provider, "thing-1", "test001", can_update=True)]
39
39
 
40
40
 
41
41
  @pytest.fixture
@@ -3,5 +3,5 @@
3
3
  More extensive example configuration, using all the features
4
4
 
5
5
  ``` yaml
6
- --8<-- "examples/config.yaml.minimal"
6
+ --8<-- "examples/config.yaml.maximal"
7
7
  ```
@@ -3,5 +3,5 @@
3
3
  Smallest working configuration
4
4
 
5
5
  ``` yaml
6
- --8<-- "examples/config.yaml.maximal"
6
+ --8<-- "examples/config.yaml.minimal"
7
7
  ```
@@ -0,0 +1,9 @@
1
+ # Docker Compose
2
+
3
+ Example Docker Compose configuration to run *updates2mqtt* as a container. This also
4
+ requires a [.env](env.md), or alternatively adding the environment variables directly into the
5
+ compose file.
6
+
7
+ ``` yaml
8
+ --8<-- "examples/docker-compose.yaml"
9
+ ```
@@ -0,0 +1,7 @@
1
+ # Environment File
2
+
3
+ Example `.env` file for Docker Compose configuration to separately store the environment variables.
4
+
5
+ ``` bash
6
+ --8<-- "examples/.env"
7
+ ```
@@ -0,0 +1,5 @@
1
+ # Example Configurations
2
+
3
+ Configuration files and Docker Compose files.
4
+
5
+ {{ pagetree(siblings) }}
@@ -16,16 +16,33 @@ The `homeassistant` default topic prefix matches the default updates2mqtt config
16
16
 
17
17
  ![Home Assistant updates in Settings](images/ha_update_page.png "Home Assistant Updates")
18
18
 
19
+ ## Device Creation
20
+
21
+ A Home Assistant device will be created for each Updates2MQTT agent on each server, and Home Assistant
22
+ will then group all the relevant entities together on this device page. Use `device_creation: false` in the
23
+ `homeassistant` config block if you want to switch off this behaviour, and `area` if you want to provide
24
+ a `suggested_area` for the device.
25
+
19
26
  ## MQTT Topics
20
27
 
21
28
  There are 3 separate types of MQTT topic used for HomeAssisstant integration:
22
29
 
23
- - *Config* to support auto discovery. A topic is created per component, with a name like `homeassistant/update/dockernuc_docker_jellyfin/update/config`. This can be disabled in the config file, and the `homeassistant` topic prefix can also be configured.
24
- - *State* to report the current version and the latest version available, again one topic per component, like `updates2mqtt/dockernuc/docker/jellyfin`.
25
- - *Command* to support triggering an update. These will be created on the fly by HomeAssistant when an update is requested, and updates2mqtt subscribes to pick up the changes, so you won't typically see these if browsing MQTT topics. Only one is needed per updates2mqtt agent, with a name like `updates2mqtt/dockernuc/docker`
30
+ - *Config* to support auto discovery.
31
+ - A topic is created per component, with a name like `homeassistant/update/dockernuc_docker_jellyfin/update/config`.
32
+ - This can be disabled in the config file, and the `homeassistant` topic prefix can also be configured.
33
+ - *State* to report the current version and the latest version available
34
+ - One topic per component, like `updates2mqtt/dockernuc/docker/jellyfin`.
35
+ - *Command* to support triggering an update.
36
+ - These will be created on the fly by HomeAssistant when an update is requested
37
+ - Updates2mqtt subscribes to pick up the changes, so you won't typically see these if browsing MQTT topics.
38
+ - Only one is needed per updates2mqtt agent, with a name like `updates2mqtt/dockernuc/docker`
26
39
 
27
40
  If the package supports automated update, then *Skip* and *Install* buttons will appear on the Home Assistant interface, and the package can be remotely fetched and the component restarted.
28
41
 
42
+ If it doesn't support automated update, the `command_topic` won't be published with the configuration
43
+ message, unless `force_command_topic` is set to `true` in the `homeassistant` configuration section,
44
+ this will force the Home Assistant app to show the update, but with a do-nothing Update button.
45
+
29
46
  ## More Home Assistant information
30
47
 
31
48
  - [MQTT Integration](https://www.home-assistant.io/integrations/mqtt/)
@@ -20,13 +20,14 @@ volumes:
20
20
  - /var/run/docker.sock:/var/run/docker.sock
21
21
  # This list of paths is only needed when containers are to be updated
22
22
  # The paths here are completely dependent on where your docker-compose files live
23
- - /home/containers:/home/containers
24
- - /dev.containers:/dev.containers
25
- - /containers:/containers
23
+ # and the internal/external paths must be exactly the same
24
+ - /my/container/home:/my/container/home
25
+ - /more/containers:/more/containers
26
26
  ```
27
27
 
28
- The example `docker-compose.yaml` mounts `/home/containers` for this purpose, so if your containers are in
29
- `/home/containers/app1`, `/home/containers/app2` etc, then updates2mqtt will be able to find them. Map as many root paths as needed.
28
+ The example `docker-compose.yaml` mounts `/my/container/home` for this purpose, so if your containers are in
29
+ `/my/container/home/app1`, `/my/container/home/app2` etc, then updates2mqtt will be able to find them in
30
+ order to restart them. Map as many root paths as needed.
30
31
 
31
32
  ### Without Docker
32
33
 
@@ -0,0 +1,4 @@
1
+ User-agent: *
2
+ Allow: /
3
+
4
+ Sitemap: https://updates2mqtt.rhizomatics.org.uk/sitemap.xml
@@ -1,3 +1,11 @@
1
+ ---
2
+ tags:
3
+ - docker
4
+ - docker-compose
5
+ - homeassistant
6
+ - mqtt
7
+ - paho
8
+ ---
1
9
  # Troubleshooting
2
10
 
3
11
  ## General
@@ -19,6 +19,9 @@ homeassistant:
19
19
  prefix: homeassistant
20
20
  enabled: true
21
21
  state_topic_suffix: state
22
+ area: Server Room
23
+ device_creation: true
24
+ force_command_topic: false
22
25
  docker:
23
26
  enabled: true
24
27
  allow_pull: true
@@ -5,7 +5,7 @@ services:
5
5
  volumes:
6
6
  - ./conf:/app/conf # Config file lives at /app/conf/config.yaml inside the container
7
7
  - /var/run/docker.sock:/var/run/docker.sock # Access to Docker daemon for container updates
8
- - /home/containers:/home/containers # Optional, map all root paths for docker compose directories
8
+ - /my/container/home:/my/container/home # Optional, map all root paths for docker compose directories
9
9
  restart: always
10
10
  env_file: ./.env # Environment variables file
11
11
  healthcheck:
@@ -4,13 +4,18 @@ site_description: Notify and take action on server updates via MQTT, with HomeAs
4
4
 
5
5
  repo_name: rhizomatics/updates2mqtt
6
6
  repo_url: https://github.com/rhizomatics/updates2mqtt
7
+ edit_uri: edit/main/docs/
7
8
 
8
9
  theme:
9
10
  name: material
10
11
  highlightjs: true
11
- logo: images/logo-blank-256x256.png
12
+ logo: images/updates2mqtt-dark-256x256.png
12
13
  language: en
14
+ icon:
15
+ repo: fontawesome/brands/github
13
16
  features:
17
+ - content.action.edit
18
+ - content.action.view
14
19
  - content.code.copy
15
20
  - content.code.select
16
21
  - content.code.annotate
@@ -24,14 +29,24 @@ theme:
24
29
  - navigation.top
25
30
  - toc.follow
26
31
  - toc.integrate
32
+ - search.suggest
33
+ - search
34
+ - search.share
27
35
  plugins:
28
36
  - search
29
37
  - autorefs
30
38
  - pagetree
31
39
  - optimize
32
- - tags
40
+ - tags:
41
+ tags: false
42
+ - git-revision-date-localized:
43
+ enable_creation_date: true
44
+ - meta-descriptions
33
45
  - minify:
34
46
  minify_html: true
47
+ - coverage:
48
+ page_path: developer/coverage
49
+ html_report_dir: htmlcov
35
50
  - mkdocstrings:
36
51
  handlers:
37
52
  # See: https://mkdocstrings.github.io/python/usage/
@@ -40,6 +55,10 @@ plugins:
40
55
  show_source: false
41
56
  show_root_heading: true
42
57
  summary: true
58
+ show_inheritance_diagram: false
59
+ overloads_only: true
60
+ show_if_no_docstring: false
61
+
43
62
  markdown_extensions:
44
63
  - admonition
45
64
  - pymdownx.details
@@ -52,7 +71,6 @@ markdown_extensions:
52
71
  pygments_lang_class: true
53
72
  - pymdownx.inlinehilite
54
73
  - pymdownx.superfences
55
- - admonition
56
74
  - smarty
57
75
  - toc:
58
76
  permalink: true
@@ -7,7 +7,7 @@ authors = [
7
7
  ]
8
8
 
9
9
  requires-python = ">=3.13"
10
- version = "1.4.1"
10
+ version = "1.5.0"
11
11
  license="Apache-2.0"
12
12
  keywords=["mqtt", "docker", "updates", "automation","home-assistant","homeassistant","selfhosting"]
13
13
 
@@ -60,14 +60,16 @@ dev = [
60
60
  "genbadge[all]"
61
61
  ]
62
62
  mkdocs=[
63
+ "mkdocs",
63
64
  "mkdocs-material",
64
- "mkdocstrings",
65
65
  "mkdocs-minify-plugin",
66
66
  "mkdocs-autorefs",
67
67
  "mkdocs-pagetree-plugin",
68
68
  "mkdocs-coverage",
69
69
  "mkdocstrings[python]",
70
70
  "pymdown-extensions",
71
+ "mkdocs-git-revision-date-localized-plugin",
72
+ "mkdocs-meta-descriptions-plugin",
71
73
  "pngquant"
72
74
  ]
73
75
 
@@ -2,6 +2,11 @@
2
2
 
3
3
  # MQTT Health Check Script
4
4
  # Checks if the heartbeat timestamp in MQTT payload is recent enough
5
+ # Requires MQTT connection details to be available as environment variables
6
+ # - MQTT_HOST (defaults to localhost)
7
+ # - MQTT_PORT (defaults to 1883)
8
+ # - MQTT_USER (no default)
9
+ # - MQTT_PASS (no default)
5
10
 
6
11
  # Arguments
7
12
  MQTT_TOPIC=$1
@@ -14,7 +14,7 @@ import structlog
14
14
  import updates2mqtt
15
15
  from updates2mqtt.model import Discovery, ReleaseProvider
16
16
 
17
- from .config import Config, load_app_config, load_package_info
17
+ from .config import Config, PackageUpdateInfo, load_app_config, load_package_info
18
18
  from .integrations.docker import DockerProvider
19
19
  from .mqtt import MqttPublisher
20
20
 
@@ -44,9 +44,9 @@ class App:
44
44
  sys.exit(1)
45
45
  self.cfg: Config = app_config
46
46
 
47
- structlog.configure(wrapper_class=structlog.make_filtering_bound_logger(getattr(logging, self.cfg.log.level)))
47
+ structlog.configure(wrapper_class=structlog.make_filtering_bound_logger(getattr(logging, str(self.cfg.log.level))))
48
48
  log.debug("Logging initialized", level=self.cfg.log.level)
49
- self.common_pkg = load_package_info(PKG_INFO_FILE)
49
+ self.common_pkg: dict[str, PackageUpdateInfo] = load_package_info(PKG_INFO_FILE)
50
50
 
51
51
  self.publisher = MqttPublisher(self.cfg.mqtt, self.cfg.node, self.cfg.homeassistant)
52
52
 
@@ -62,25 +62,29 @@ class App:
62
62
  "App configured",
63
63
  node=self.cfg.node.name,
64
64
  scan_interval=self.cfg.scan_interval,
65
+ healthcheck_topic=self.healthcheck_topic,
65
66
  )
66
67
 
67
68
  async def scan(self) -> None:
68
69
  session = uuid.uuid4().hex
69
70
  for scanner in self.scanners:
70
- log.info("Cleaning topics before scan", source_type=scanner.source_type)
71
+ slog = log.bind(source_type=scanner.source_type, session=session)
72
+ slog.info("Cleaning topics before scan")
71
73
  if self.scan_count == 0:
72
74
  await self.publisher.clean_topics(scanner, None, force=True)
73
75
  if self.stopped.is_set():
74
76
  break
75
- log.info("Scanning", source=scanner.source_type, session=session)
77
+ slog.info("Scanning ...")
76
78
  async with asyncio.TaskGroup() as tg:
77
- async for discovery in scanner.scan(session): # xtype: ignore[attr-defined]
79
+ # xtype: ignore[attr-defined]
80
+ async for discovery in scanner.scan(session):
78
81
  tg.create_task(self.on_discovery(discovery), name=f"discovery-{discovery.name}")
79
82
  if self.stopped.is_set():
83
+ slog.debug("Breaking scan loop on stopped event")
80
84
  break
81
85
  await self.publisher.clean_topics(scanner, session, force=False)
82
86
  self.scan_count += 1
83
- log.info("Scan complete", source_type=scanner.source_type)
87
+ slog.info(f"Scan #{self.scan_count} complete")
84
88
  self.last_scan_timestamp = datetime.now(UTC).isoformat()
85
89
 
86
90
  async def main_loop(self) -> None:
@@ -170,13 +174,15 @@ class App:
170
174
  async def healthcheck(self) -> None:
171
175
  if not self.publisher.is_available():
172
176
  return
177
+ heartbeat_stamp: str = datetime.now(UTC).isoformat()
178
+ log.debug("Publishing health check", heartbeat_stamp=heartbeat_stamp)
173
179
  self.publisher.publish(
174
180
  topic=self.healthcheck_topic,
175
181
  payload={
176
182
  "version": updates2mqtt.version, # pyright: ignore[reportAttributeAccessIssue]
177
183
  "node": self.cfg.node.name,
178
184
  "heartbeat_raw": time.time(),
179
- "heartbeat_stamp": datetime.now(UTC).isoformat(),
185
+ "heartbeat_stamp": heartbeat_stamp,
180
186
  "startup_stamp": self.startup_timestamp,
181
187
  "last_scan_stamp": self.last_scan_timestamp,
182
188
  "scan_count": self.scan_count,
@@ -191,7 +197,7 @@ async def repeated_call(func: Callable, interval: int = 60, *args: Any, **kwargs
191
197
  await func(*args, **kwargs)
192
198
  await asyncio.sleep(interval)
193
199
  except asyncio.CancelledError:
194
- log.debug("Periodic task cancelled")
200
+ log.debug("Periodic task cancelled", func=func)
195
201
  except Exception:
196
202
  log.exception("Periodic task failed")
197
203
 
@@ -202,6 +208,7 @@ def run() -> None:
202
208
 
203
209
  from .app import App
204
210
 
211
+ # pyright: ignore[reportAttributeAccessIssue]
205
212
  log.debug(f"Starting updates2mqtt v{updates2mqtt.version}") # pyright: ignore[reportAttributeAccessIssue]
206
213
  app = App()
207
214