updates2mqtt 1.4.0__tar.gz → 1.4.2__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 (65) hide show
  1. updates2mqtt-1.4.2/.github/workflows/auto_assign_issue.yml +18 -0
  2. updates2mqtt-1.4.2/.github/workflows/auto_assign_pr.yml +18 -0
  3. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.github/workflows/docker-publish.yml +2 -2
  4. updates2mqtt-1.4.2/.github/workflows/main.yml +18 -0
  5. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.github/workflows/pypi-publish.yml +4 -1
  6. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.github/workflows/python-package.yml +23 -2
  7. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.gitignore +1 -0
  8. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.pre-commit-config.yaml +2 -2
  9. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/CHANGELOG.md +9 -0
  10. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/PKG-INFO +11 -2
  11. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/README.md +10 -1
  12. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/common_packages.yaml +26 -2
  13. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/conftest.py +68 -5
  14. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/home_assistant.md +7 -0
  15. updates2mqtt-1.4.2/docs/images/updates2mqtt-dark-256x256.png +0 -0
  16. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/installation.md +16 -2
  17. updates2mqtt-1.4.2/docs/robots.txt +4 -0
  18. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/troubleshooting.md +80 -2
  19. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/examples/config.yaml.maximal +2 -0
  20. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/examples/docker-compose.yaml +1 -1
  21. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/mkdocs.yml +21 -3
  22. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/pyproject.toml +8 -3
  23. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/app.py +15 -10
  24. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/config.py +3 -1
  25. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/hass_formatter.py +20 -4
  26. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/integrations/docker.py +10 -4
  27. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/model.py +4 -0
  28. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/mqtt.py +14 -11
  29. updates2mqtt-1.4.2/tests/test_app.py +130 -0
  30. updates2mqtt-1.4.2/tests/test_hass_formatter.py +68 -0
  31. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/tests/test_mqtt.py +6 -6
  32. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/uv.lock +251 -45
  33. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.dockerignore +0 -0
  34. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.github/dependabot.yml +0 -0
  35. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.hintrc +0 -0
  36. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.python-version +0 -0
  37. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/.safety-project.ini +0 -0
  38. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/Dockerfile +0 -0
  39. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/LICENSE +0 -0
  40. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/SECURITY.md +0 -0
  41. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/configuration.md +0 -0
  42. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/examples/config_maximal.md +0 -0
  43. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/examples/config_minimal.md +0 -0
  44. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/examples/docker_compose.md +0 -0
  45. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/ha_entities.png +0 -0
  46. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/ha_mqtt_discovery.png +0 -0
  47. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/ha_update_detail.png +0 -0
  48. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/ha_update_dialog.png +0 -0
  49. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/ha_update_page.png +0 -0
  50. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/images/logo-blank-256x256.png +0 -0
  51. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/index.md +0 -0
  52. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/docs/local_builds.md +0 -0
  53. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/examples/config.yaml.minimal +0 -0
  54. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/no_config.yaml +0 -0
  55. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/refresh-deps.sh +0 -0
  56. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/scripts/healthcheck.sh +0 -0
  57. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/__init__.py +0 -0
  58. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/__main__.py +0 -0
  59. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/integrations/__init__.py +0 -0
  60. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/integrations/git_utils.py +0 -0
  61. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/src/updates2mqtt/py.typed +0 -0
  62. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/tests/__init__.py +0 -0
  63. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/tests/test_config.py +0 -0
  64. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/tests/test_docker.py +0 -0
  65. {updates2mqtt-1.4.0 → updates2mqtt-1.4.2}/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
@@ -25,7 +25,7 @@ jobs:
25
25
  #
26
26
  steps:
27
27
  - name: Checkout repository
28
- uses: actions/checkout@v5
28
+ uses: actions/checkout@v6
29
29
  # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
30
30
  - name: Log in to the Container registry
31
31
  uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
@@ -42,7 +42,7 @@ jobs:
42
42
  uses: docker/setup-buildx-action@v3
43
43
  - name: Extract metadata (tags, labels) for Docker
44
44
  id: meta
45
- uses: docker/metadata-action@8d8c7c12f7b958582a5cb82ba16d5903cb27976a
45
+ uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051
46
46
  with:
47
47
  images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
48
48
  tags: |
@@ -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
@@ -2,13 +2,16 @@ name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
2
2
 
3
3
  on: push
4
4
 
5
+ permissions:
6
+ contents: read
7
+
5
8
  jobs:
6
9
  build:
7
10
  name: Build distribution 📦
8
11
  runs-on: ubuntu-latest
9
12
 
10
13
  steps:
11
- - uses: actions/checkout@v5
14
+ - uses: actions/checkout@v6
12
15
  with:
13
16
  persist-credentials: false
14
17
  - name: uv-setup
@@ -15,7 +15,7 @@ jobs:
15
15
  permissions:
16
16
  contents: write
17
17
  steps:
18
- - uses: actions/checkout@v5
18
+ - uses: actions/checkout@v6
19
19
  - name: uv-setup
20
20
  # Install a specific uv version using the installer
21
21
  run: curl -LsSf https://astral.sh/uv/install.sh | sh
@@ -27,11 +27,32 @@ jobs:
27
27
  run: uv sync --all-extras --dev
28
28
 
29
29
  - name: Ruff
30
- uses: chartboost/ruff-action@v1
30
+ uses: astral-sh/ruff-action@v3
31
31
  - name: Test with pytest
32
32
  run: uv run pytest tests
33
33
  - name: Build a binary wheel and a source tarball
34
34
  run: uv build
35
+ - name: Generate badges
36
+ env:
37
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38
+ run: |
39
+ uv run genbadge coverage -i cov.xml -o badges/coverage.svg
40
+ uv run genbadge tests -i junit/test-results.xml -o badges/tests.svg
41
+
42
+ git config --global user.name "github-actions[bot]"
43
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
44
+ TEMP_DIR=$(mktemp -d)
45
+ cd $TEMP_DIR
46
+ git clone --single-branch --branch badges https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git . 2>/dev/null
47
+ cp -r ${{ github.workspace }}/badges .
48
+ git add badges
49
+ if git commit -m "Update badges [skip ci]"; then
50
+ git push origin badges --force
51
+ echo "Badges updated successfully"
52
+ else
53
+ echo "No changes to badges"
54
+ fi
55
+
35
56
  - name: Prep for mkdocs
36
57
  run: uv pip compile pyproject.toml -o requirements_docs.txt --group mkdocs
37
58
  - name: Deploy docs
@@ -11,6 +11,7 @@ htmlcov/
11
11
  lcov.info
12
12
  .vscode/
13
13
  .DS_Store
14
+ junit/
14
15
 
15
16
  # C extensions
16
17
  *.so
@@ -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
@@ -1,5 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.4.2
4
+ - Replace `origin` in config MQTT message with `device` for better HomeAssistant compatibility
5
+ - An `area` can be defined in the Home Assistant section of config and this will then be used as `suggested_area` for device
6
+ - Icon and release note info added for Owntone and Homarr
7
+ ## 1.4.1
8
+ - More logging for Docker discovery on why Home Assistant doesn't show an update button
9
+ - More test cases
10
+ - `MqttClient` is now `MqttPublisher` to avoid confusion with actual MQTT client
11
+ - Task cleanup now only interrupts explicit list of tasks - healthcheck and discovery tasks
3
12
  ## 1.4.0
4
13
  - MQTT protocol can now be set, to one of `3.1`,`3.11` or `5`
5
14
  - Debug messages now provided for `on_subscribe` and `on_unsubscribe` callbacks
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: updates2mqtt
3
- Version: 1.4.0
3
+ Version: 1.4.2
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,18 +35,27 @@ 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
 
42
+ [![Rhizomatics Open Source](https://img.shields.io/badge/rhizomatics%20open%20source-lightseagreen)](https://github.com/rhizomatics)
43
+
42
44
  [![PyPI - Version](https://img.shields.io/pypi/v/updates2mqtt)](https://pypi.org/project/updates2mqtt/)
43
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/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)
44
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)
45
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)
46
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)
47
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)
48
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)
49
53
 
54
+
55
+ <br/>
56
+ <br/>
57
+
58
+
50
59
  ## Summary
51
60
 
52
61
  Let Home Assistant tell you about new updates to Docker images for your containers.
@@ -1,15 +1,24 @@
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
 
5
+ [![Rhizomatics Open Source](https://img.shields.io/badge/rhizomatics%20open%20source-lightseagreen)](https://github.com/rhizomatics)
6
+
5
7
  [![PyPI - Version](https://img.shields.io/pypi/v/updates2mqtt)](https://pypi.org/project/updates2mqtt/)
6
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/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)
7
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)
8
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)
9
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)
10
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)
11
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)
12
16
 
17
+
18
+ <br/>
19
+ <br/>
20
+
21
+
13
22
  ## Summary
14
23
 
15
24
  Let Home Assistant tell you about new updates to Docker images for your containers.
@@ -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,28 @@ 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
@@ -1,26 +1,89 @@
1
- from unittest.mock import MagicMock, Mock, patch
1
+ # python
2
+ from collections.abc import AsyncGenerator, Callable
3
+ from typing import Any
4
+ from unittest.mock import AsyncMock, MagicMock, Mock, patch
2
5
 
3
6
  import paho.mqtt.client
4
7
  import pytest
5
8
  from docker import DockerClient
6
9
  from docker.models.containers import Container, ContainerCollection
7
10
  from docker.models.images import Image, RegistryData
11
+ from omegaconf import DictConfig, OmegaConf
8
12
 
13
+ import updates2mqtt.app
14
+ from updates2mqtt.app import (
15
+ App, # relative import as required
16
+ MqttPublisher,
17
+ )
18
+ from updates2mqtt.config import Config
9
19
  from updates2mqtt.model import Discovery, ReleaseProvider
10
20
 
11
21
 
22
+ @pytest.fixture
23
+ def app_with_mocked_external_dependencies(
24
+ monkeypatch, # noqa: ANN001
25
+ mock_provider_class: type,
26
+ mock_publisher_class: type,
27
+ ) -> App:
28
+ cfg: DictConfig = OmegaConf.structured(Config)
29
+ monkeypatch.setattr(updates2mqtt.app, "load_app_config", lambda *_args, **__kwargs: cfg)
30
+ monkeypatch.setattr(updates2mqtt.app, "DockerProvider", mock_provider_class)
31
+ monkeypatch.setattr(updates2mqtt.app, "MqttPublisher", mock_publisher_class)
32
+ app: App = App()
33
+ return app
34
+
35
+
36
+ @pytest.fixture
37
+ def mock_discoveries(mock_provider: ReleaseProvider) -> list[Discovery]:
38
+ return [Discovery(mock_provider, "thing-1", "test001")]
39
+
40
+
41
+ @pytest.fixture
42
+ def mock_discovery_generator(mock_discoveries: list[Discovery]) -> Callable[..., AsyncGenerator[Discovery, Any]]:
43
+ async def g(*args: Any) -> AsyncGenerator[Discovery]: # noqa: ARG001
44
+ for d in mock_discoveries:
45
+ yield d
46
+
47
+ return g
48
+
49
+
50
+ @pytest.fixture
51
+ def mock_provider_class(mock_provider: ReleaseProvider) -> type:
52
+ class MockReleaseProvider(ReleaseProvider):
53
+ def __new__(cls, *args: Any, **kwargs: Any) -> ReleaseProvider: # type: ignore[misc] # noqa: ARG004
54
+ return mock_provider
55
+
56
+ return MockReleaseProvider
57
+
58
+
59
+ @pytest.fixture
60
+ def mock_publisher_class(mock_publisher: MqttPublisher) -> type:
61
+ class MockPublisher(MqttPublisher):
62
+ def __new__(cls, *args: Any, **kwargs: Any) -> MqttPublisher: # type: ignore[misc] # noqa: ARG004
63
+ return mock_publisher
64
+
65
+ return MockPublisher
66
+
67
+
12
68
  @pytest.fixture
13
69
  def mock_provider() -> ReleaseProvider:
14
- provider = Mock(spec=ReleaseProvider)
70
+ provider: ReleaseProvider = AsyncMock(spec=ReleaseProvider)
15
71
  provider.source_type = "unit_test"
16
- provider.command.return_value = True
17
- provider.resolve.return_value = Discovery(
72
+ provider.command.return_value = True # type: ignore[attr-defined]
73
+ provider.resolve.return_value = Discovery( # type: ignore[attr-defined]
18
74
  provider, "fooey", session="test-mqtt-123", current_version="v2", latest_version="v2"
19
75
  )
20
- provider.hass_state_format.return_value = {"fixture": "test_exec"}
76
+ provider.hass_state_format.return_value = {"fixture": "test_exec"} # type: ignore[attr-defined]
21
77
  return provider
22
78
 
23
79
 
80
+ @pytest.fixture
81
+ def mock_publisher(mock_mqtt_client: paho.mqtt.client.Client) -> MqttPublisher:
82
+ publisher: MqttPublisher = AsyncMock(MqttPublisher)
83
+ publisher.client = mock_mqtt_client
84
+ return publisher
85
+
86
+
24
87
  @pytest.fixture
25
88
  def mock_mqtt_client() -> paho.mqtt.client.Client:
26
89
  return MagicMock(spec=paho.mqtt.client.Client, name="MQTT Client Fixture")
@@ -16,6 +16,13 @@ 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:
@@ -12,8 +12,22 @@ See `examples` directory for a working `docker-compose.yaml`.
12
12
 
13
13
  If you want to update and restart containers, then the file system paths to the location of the directory where the docker compose file lives must be available in the updates2mqtt container.
14
14
 
15
- The example `docker-compose.yaml` mounts `/home/containers` for this purpose, so if your containers are in
16
- `/home/containers/app1`, `/home/containers/app2` etc, then updates2mqtt will be able to find them. Map as many root paths as needed.
15
+ ```yaml
16
+ volumes:
17
+ # Must have config directory mapped
18
+ - ./conf:/app/conf
19
+ # Must have the Docker daemon socket mapped
20
+ - /var/run/docker.sock:/var/run/docker.sock
21
+ # This list of paths is only needed when containers are to be updated
22
+ # The paths here are completely dependent on where your docker-compose files live
23
+ # and the internal/external paths must be exactly the same
24
+ - /my/container/home:/my/container/home
25
+ - /more/containers:/more/containers
26
+ ```
27
+
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.
17
31
 
18
32
  ### Without Docker
19
33
 
@@ -0,0 +1,4 @@
1
+ User-agent: *
2
+ Allow: /
3
+
4
+ Sitemap: https://updates2mqtt.rhizomatics.org.uk/sitemap.xml
@@ -1,14 +1,60 @@
1
+ ---
2
+ tags:
3
+ - docker
4
+ - docker-compose
5
+ - homeassistant
6
+ - mqtt
7
+ - paho
8
+ ---
1
9
  # Troubleshooting
2
10
 
3
- ## Log Level
11
+ ## General
4
12
 
5
- Update the `config.yaml` and change the log level to DEBUG
13
+ Things that need to work:
14
+
15
+ - Docker API access to list and inspect containers
16
+ - MQTT Publication of results
17
+ - Home Assistant discovering the Update entities on MQTT
18
+ - Home Assistant generating update notices in UI when there's a new version
19
+ - Command Topic message sent by Home Assistant when Update button clicked
20
+ - Docker Compose available from shell to make updates and restart
21
+ - Git command available in shell to check for local repo updates and pull
22
+
23
+ ## Updates2MQTT Logs
24
+
25
+ If running under docker, and following the container naming guidance, then see the
26
+ logs using:
27
+
28
+ `docker logs updates2mqtt`
29
+
30
+ or change to the directory where the `docker-compose.yaml` is installed and do `docker compose logs`
31
+
32
+ ### Changing Log Level
33
+
34
+ Update the `config.yaml` and change the log level to DEBUG, which will show much
35
+ more diagnostic information.
6
36
 
7
37
  ```yaml
8
38
  log:
9
39
  level: DEBUG
10
40
  ```
11
41
 
42
+ When you have everything working, its best to change the log level back, so
43
+ your container isn't generating big logs.
44
+
45
+ ### Going Inside Container
46
+
47
+ From the `docker-compose.yaml` directory, execute
48
+
49
+ `docker compose exec -it updates2mqtt bash`
50
+
51
+ (if you have an old Docker install, you may need to use `docker-compose` instead of `docker compose`)
52
+
53
+ This will give you shell access inside the container, which is a good way of checking
54
+ for path issues, permissio issues etc. For example, if you have compose directories in the
55
+ `/containers` directory, you could `cd /containers` and validate that Updates2MQTT can see the
56
+ other compose directories, `ls` the contents, and run `docker compose` or `git` actions there.
57
+
12
58
  ## MQTT
13
59
 
14
60
  If the host, port, user and password for MQTT are incorrect then usually this
@@ -58,6 +104,38 @@ Oddly, the Paho MQTT client used by Updates2MQTT is known to [report success eve
58
104
 
59
105
  There's also an alternative to MQTT Discovery in HA, using plain yaml, the [MQTT Update Integration](https://www.home-assistant.io/integrations/update.mqtt/#configuration). The [BBQKees Boiler Gateway](https://bbqkees-electronics.nl/wiki/home-automations/home-assistant-configuration.html) has some detailed steps and examples for MQTT Discovery too.
60
106
 
107
+ #### No Update Button
108
+
109
+ If there's an update showing, but no *Update* button present, then there's a few reasons, which
110
+ can be checked directly from the config and log:
111
+
112
+ - Config has the `allow_pull`,`allow_restart` and `allow_build` all overridden to `False`
113
+ - A new version reference can't be found
114
+ - The compose working directory can't be found
115
+ - This is sourced from the `com.docker.compose.project.working_dir` label, which can be seen in `docker inspect`
116
+ - This only stops restart, not pull, so if `allow_pull` is on, the Update button will still show
117
+ - The git repo path can't be found for a local build
118
+
119
+ The current state of this can be seen in MQTT, the config message will have two extra
120
+ values as below:
121
+
122
+ ```yaml
123
+ "command_topic": "updates2mqtt/dockernuc/docker",
124
+ "payload_install": "docker|homarr|install"
125
+ ```
126
+
127
+ #### Home Assistant Logs
128
+
129
+ Use the [System Log](https://www.home-assistant.io/integrations/system_log/) to check
130
+ for MQTT errors, or for positive confirmation that Update entities have been discovered. The
131
+ *raw* log will show more, and allow you to scroll back for hours.
132
+
133
+ The [Logger Integration](https://www.home-assistant.io/integrations/logger/#viewing-logs)
134
+ lets you tweak the levels of specific integrations. This is less useful for Updates2MQTT,
135
+ since all the work is happening outside of Home Assistant, however it can be useful
136
+ for general MQTT issues, and the examples in the Home Assistant documentation shows how
137
+ to tune the MQTT integration.
138
+
61
139
  ## Docker
62
140
 
63
141
  More detailed information on the Docker API and compatibility with Docker engine versions can be found at Docker's own [Docker Engine API](https://docs.docker.com/reference/api/engine/) reference.
@@ -19,6 +19,8 @@ homeassistant:
19
19
  prefix: homeassistant
20
20
  enabled: true
21
21
  state_topic_suffix: state
22
+ area: Server Room
23
+ device_creation: true
22
24
  docker:
23
25
  enabled: true
24
26
  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.0"
10
+ version = "1.4.2"
11
11
  license="Apache-2.0"
12
12
  keywords=["mqtt", "docker", "updates", "automation","home-assistant","homeassistant","selfhosting"]
13
13
 
@@ -56,16 +56,20 @@ dev = [
56
56
  "pytest-mqtt>=0.6.0",
57
57
  "pytest-subprocess>=1.5.3",
58
58
  "coverage",
59
+ "icdiff",
60
+ "genbadge[all]"
59
61
  ]
60
62
  mkdocs=[
63
+ "mkdocs",
61
64
  "mkdocs-material",
62
- "mkdocstrings",
63
65
  "mkdocs-minify-plugin",
64
66
  "mkdocs-autorefs",
65
67
  "mkdocs-pagetree-plugin",
66
68
  "mkdocs-coverage",
67
69
  "mkdocstrings[python]",
68
70
  "pymdown-extensions",
71
+ "mkdocs-git-revision-date-localized-plugin",
72
+ "mkdocs-meta-descriptions-plugin",
69
73
  "pngquant"
70
74
  ]
71
75
 
@@ -154,10 +158,11 @@ norecursedirs = [
154
158
  ".git",
155
159
  "templates",
156
160
  ]
161
+
157
162
  pythonpath = [
158
163
  "."
159
164
  ]
160
- addopts = "--cov --cov-report=lcov:lcov.info --cov-report=term --import-mode=importlib"
165
+ addopts = "--junitxml=junit/test-results.xml --cov --cov-report=lcov:lcov.info --cov-report=xml --cov-report=html --cov-report=term --import-mode=importlib"
161
166
 
162
167
  [tool.coverage.run]
163
168
  branch = true