updates2mqtt 1.3.7__tar.gz → 1.4.1__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.
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.github/dependabot.yml +6 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.github/workflows/docker-publish.yml +2 -2
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.github/workflows/pypi-publish.yml +7 -4
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.github/workflows/python-package.yml +26 -3
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.gitignore +1 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.pre-commit-config.yaml +5 -5
- updates2mqtt-1.4.1/CHANGELOG.md +22 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/Dockerfile +1 -1
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/PKG-INFO +69 -23
- updates2mqtt-1.4.1/README.md +128 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/conftest.py +68 -5
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/configuration.md +50 -19
- updates2mqtt-1.4.1/docs/home_assistant.md +34 -0
- updates2mqtt-1.4.1/docs/images/ha_entities.png +0 -0
- updates2mqtt-1.4.1/docs/images/ha_update_dialog.png +0 -0
- updates2mqtt-1.4.1/docs/images/logo-blank-256x256.png +0 -0
- updates2mqtt-1.4.1/docs/installation.md +57 -0
- updates2mqtt-1.4.1/docs/troubleshooting.md +163 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/examples/config.yaml.maximal +1 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/mkdocs.yml +24 -1
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/pyproject.toml +10 -2
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/app.py +15 -10
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/config.py +1 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/integrations/docker.py +11 -5
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/integrations/git_utils.py +3 -1
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/model.py +4 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/mqtt.py +54 -9
- updates2mqtt-1.4.1/tests/test_app.py +130 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/tests/test_docker.py +8 -7
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/tests/test_mqtt.py +9 -8
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/uv.lock +370 -124
- updates2mqtt-1.3.7/CHANGELOG.md +0 -12
- updates2mqtt-1.3.7/README.md +0 -82
- updates2mqtt-1.3.7/docs/installation.md +0 -29
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.dockerignore +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.hintrc +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.python-version +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/.safety-project.ini +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/LICENSE +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/SECURITY.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/common_packages.yaml +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/examples/config_maximal.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/examples/config_minimal.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/examples/docker_compose.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/images/ha_mqtt_discovery.png +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/images/ha_update_detail.png +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/images/ha_update_page.png +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/index.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/docs/local_builds.md +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/examples/config.yaml.minimal +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/examples/docker-compose.yaml +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/no_config.yaml +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/refresh-deps.sh +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/scripts/healthcheck.sh +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/__init__.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/__main__.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/hass_formatter.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/integrations/__init__.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/src/updates2mqtt/py.typed +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/tests/__init__.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/tests/test_config.py +0 -0
- {updates2mqtt-1.3.7 → updates2mqtt-1.4.1}/tests/test_git_utils.py +0 -0
|
@@ -9,16 +9,22 @@ updates:
|
|
|
9
9
|
directory: "/" # Location of package manifests
|
|
10
10
|
schedule:
|
|
11
11
|
interval: "weekly"
|
|
12
|
+
cooldown:
|
|
13
|
+
default-days: 7
|
|
12
14
|
|
|
13
15
|
- package-ecosystem: "github-actions"
|
|
14
16
|
directory: "/"
|
|
15
17
|
schedule:
|
|
16
18
|
interval: "monthly"
|
|
19
|
+
cooldown:
|
|
20
|
+
default-days: 7
|
|
17
21
|
|
|
18
22
|
- package-ecosystem: "docker"
|
|
19
23
|
directory: "/"
|
|
20
24
|
schedule:
|
|
21
25
|
interval: "weekly"
|
|
26
|
+
cooldown:
|
|
27
|
+
default-days: 7
|
|
22
28
|
|
|
23
29
|
|
|
24
30
|
|
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
#
|
|
26
26
|
steps:
|
|
27
27
|
- name: Checkout repository
|
|
28
|
-
uses: actions/checkout@
|
|
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@
|
|
45
|
+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051
|
|
46
46
|
with:
|
|
47
47
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
48
48
|
tags: |
|
|
@@ -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@
|
|
14
|
+
- uses: actions/checkout@v6
|
|
12
15
|
with:
|
|
13
16
|
persist-credentials: false
|
|
14
17
|
- name: uv-setup
|
|
@@ -22,7 +25,7 @@ jobs:
|
|
|
22
25
|
- name: Build a binary wheel and a source tarball
|
|
23
26
|
run: uv build
|
|
24
27
|
- name: Store the distribution packages
|
|
25
|
-
uses: actions/upload-artifact@
|
|
28
|
+
uses: actions/upload-artifact@v5
|
|
26
29
|
with:
|
|
27
30
|
name: python-package-distributions
|
|
28
31
|
path: dist/
|
|
@@ -42,7 +45,7 @@ jobs:
|
|
|
42
45
|
|
|
43
46
|
steps:
|
|
44
47
|
- name: Download all the dists
|
|
45
|
-
uses: actions/download-artifact@
|
|
48
|
+
uses: actions/download-artifact@v6
|
|
46
49
|
with:
|
|
47
50
|
name: python-package-distributions
|
|
48
51
|
path: dist/
|
|
@@ -64,7 +67,7 @@ jobs:
|
|
|
64
67
|
|
|
65
68
|
steps:
|
|
66
69
|
- name: Download all the dists
|
|
67
|
-
uses: actions/download-artifact@
|
|
70
|
+
uses: actions/download-artifact@v6
|
|
68
71
|
with:
|
|
69
72
|
name: python-package-distributions
|
|
70
73
|
path: dist/
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
permissions:
|
|
16
16
|
contents: write
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
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
|
|
@@ -25,18 +25,41 @@ jobs:
|
|
|
25
25
|
python-version-file: "pyproject.toml"
|
|
26
26
|
- name: Install dependencies
|
|
27
27
|
run: uv sync --all-extras --dev
|
|
28
|
+
|
|
28
29
|
- name: Ruff
|
|
29
|
-
uses:
|
|
30
|
+
uses: astral-sh/ruff-action@v3
|
|
30
31
|
- name: Test with pytest
|
|
31
32
|
run: uv run pytest tests
|
|
32
33
|
- name: Build a binary wheel and a source tarball
|
|
33
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
|
+
|
|
34
56
|
- name: Prep for mkdocs
|
|
35
|
-
run:
|
|
57
|
+
run: uv pip compile pyproject.toml -o requirements_docs.txt --group mkdocs
|
|
36
58
|
- name: Deploy docs
|
|
37
59
|
uses: mhausenblas/mkdocs-deploy-gh-pages@master
|
|
38
60
|
env:
|
|
39
61
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
62
|
+
EXTRA_PACKAGES: pngquant
|
|
40
63
|
REQUIREMENTS: requirements_docs.txt
|
|
41
64
|
CUSTOM_DOMAIN: updates2mqtt.rhizomatics.org.uk
|
|
42
65
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/asottile/pyupgrade
|
|
3
|
-
rev: v3.21.
|
|
3
|
+
rev: v3.21.2
|
|
4
4
|
hooks:
|
|
5
5
|
- id: pyupgrade
|
|
6
6
|
args: [--py313-plus]
|
|
@@ -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.
|
|
20
|
+
rev: 0.9.13
|
|
21
21
|
hooks:
|
|
22
22
|
- id: uv-lock
|
|
23
23
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
24
|
-
rev: v0.14.
|
|
24
|
+
rev: v0.14.7
|
|
25
25
|
hooks:
|
|
26
26
|
# Run the linter.
|
|
27
27
|
- id: ruff-check
|
|
@@ -39,7 +39,7 @@ repos:
|
|
|
39
39
|
exclude_types: [csv, json]
|
|
40
40
|
|
|
41
41
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
42
|
-
rev: v1.
|
|
42
|
+
rev: v1.19.0
|
|
43
43
|
hooks:
|
|
44
44
|
- id: mypy
|
|
45
45
|
args:
|
|
@@ -64,7 +64,7 @@ repos:
|
|
|
64
64
|
- usingversion
|
|
65
65
|
|
|
66
66
|
- repo: https://github.com/PyCQA/bandit
|
|
67
|
-
rev: '1.
|
|
67
|
+
rev: '1.9.2'
|
|
68
68
|
hooks:
|
|
69
69
|
- id: bandit
|
|
70
70
|
args: ["-c", "pyproject.toml"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 1.4.1
|
|
4
|
+
- More logging for Docker discovery on why Home Assistant doesn't show an update button
|
|
5
|
+
- More test cases
|
|
6
|
+
- `MqttClient` is now `MqttPublisher` to avoid confusion with actual MQTT client
|
|
7
|
+
- Task cleanup now only interrupts explicit list of tasks - healthcheck and discovery tasks
|
|
8
|
+
## 1.4.0
|
|
9
|
+
- MQTT protocol can now be set, to one of `3.1`,`3.11` or `5`
|
|
10
|
+
- Debug messages now provided for `on_subscribe` and `on_unsubscribe` callbacks
|
|
11
|
+
- Troubleshooting, installation, configuration docs updated, images optimized
|
|
12
|
+
|
|
13
|
+
## 1.3.7
|
|
14
|
+
- Improved initial setup when run without config or env vars for MQTT
|
|
15
|
+
- Minor test deps update and pyproject docs
|
|
16
|
+
|
|
17
|
+
## 1.3.6
|
|
18
|
+
- Changed exit code on graceful shutdown to 143
|
|
19
|
+
- App now exits if the MQTT username / password is not authorized
|
|
20
|
+
- Improved handling of env vars, default config now assumes MQTT_HOST etc unless overridden
|
|
21
|
+
- 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`)
|
|
22
|
+
- Deps update
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: updates2mqtt
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
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
|
|
@@ -39,8 +39,12 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
|
|
40
40
|
# updates2mqtt
|
|
41
41
|
|
|
42
|
+
[](https://github.com/rhizomatics)
|
|
43
|
+
|
|
42
44
|
[](https://pypi.org/project/updates2mqtt/)
|
|
43
45
|
[](https://github.com/rhizomatics/supernotify)
|
|
46
|
+

|
|
47
|
+

|
|
44
48
|
[](https://results.pre-commit.ci/latest/github/rhizomatics/updates2mqtt/main)
|
|
45
49
|
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml)
|
|
46
50
|
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml)
|
|
@@ -49,9 +53,14 @@ Description-Content-Type: text/markdown
|
|
|
49
53
|
|
|
50
54
|
## Summary
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
Let Home Assistant tell you about new updates to Docker images for your containers.
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
Read the release notes, and optionally click *Update* to trigger a Docker *pull* (or optionally *build*) and *update*.
|
|
61
|
+
|
|
62
|
+
{width=480}
|
|
53
63
|
|
|
54
|
-

|
|
55
64
|
|
|
56
65
|
## Description
|
|
57
66
|
|
|
@@ -59,7 +68,7 @@ updates2mqtt perioidically checks for new versions of components being available
|
|
|
59
68
|
|
|
60
69
|
Currently only Docker containers are supported, either via an image registry check, or a git repo for source (see [Local Builds](local_builds.md)). The design is modular, so other update sources can be added, at least for notification. The next anticipated is **apt** for Debian based systems.
|
|
61
70
|
|
|
62
|
-
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience.
|
|
71
|
+
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience. See [Home Assistant Integration](home_assistant.md) for details.
|
|
63
72
|
|
|
64
73
|
To get started, read the [Installation](installation.md) and [Configuration](configuration.md) pages.
|
|
65
74
|
|
|
@@ -71,8 +80,7 @@ docker run -e MQTT_USER=user1 -e MQTT_PASS=pass1 -e MQTT_HOST=192.168.1.5 ghcr.i
|
|
|
71
80
|
|
|
72
81
|
## Release Support
|
|
73
82
|
|
|
74
|
-
Presently only Docker containers are supported, although others are planned,
|
|
75
|
-
probably with priority for `apt`.
|
|
83
|
+
Presently only Docker containers are supported, although others are planned, probably with priority for `apt`.
|
|
76
84
|
|
|
77
85
|
| Ecosystem | Support | Comments |
|
|
78
86
|
|-----------|-------------|----------------------------------------------------------------------------------------------------|
|
|
@@ -82,31 +90,57 @@ probably with priority for `apt`.
|
|
|
82
90
|
|
|
83
91
|
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.
|
|
84
92
|
|
|
85
|
-
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`.
|
|
93
|
+
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.
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
## HomeAssistant integration
|
|
95
|
+
!!! tip
|
|
90
96
|
|
|
91
|
-
|
|
92
|
-
Home Assistant settings page if the [MQTT Integration](https://www.home-assistant.io/integrations/mqtt/) is installed and automatic discovery is not disabled.
|
|
97
|
+
Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq`
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
Another approach is using a restarter service directly in Docker Compose to force a restart, in this case once a day:
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
```yaml title="Example Compose Service"
|
|
102
|
+
restarter:
|
|
103
|
+
image: docker:cli
|
|
104
|
+
volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
|
|
105
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart updates2mqtt; done"]
|
|
106
|
+
restart: unless-stopped
|
|
107
|
+
environment:
|
|
108
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
109
|
+
```
|
|
97
110
|
|
|
98
|
-
|
|
111
|
+
## Target Containers
|
|
99
112
|
|
|
100
|
-
|
|
113
|
+
While `updates2mqtt` will discover and monitor all containers running under the Docker daemon,
|
|
114
|
+
there are some options to make to those containers to tune how it works.
|
|
101
115
|
|
|
102
|
-
|
|
116
|
+
These happen by adding environment variables to the containers, typically inside an `.env`
|
|
117
|
+
file, or as `environment` options inside `docker-compose.yaml`.
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
### Automated updates
|
|
120
|
+
|
|
121
|
+
If Docker containers should be immediately updated, without any confirmation
|
|
122
|
+
or trigger, *e.g.* from the HomeAssistant update dialog, then set an environment variable `UPD2MQTT_UPDATE` in the target container to `Auto` ( it defaults to `Passive`)
|
|
123
|
+
|
|
124
|
+
```yaml title="Example Compose Snippet"
|
|
125
|
+
restarter:
|
|
126
|
+
image: docker:cli
|
|
127
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart mailserver; done"]
|
|
128
|
+
environment:
|
|
129
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Environment Variables
|
|
133
|
+
|
|
134
|
+
The following environment variables can be used to configure containers for `updates2mqtt`:
|
|
135
|
+
|
|
136
|
+
| Env Var | Description | Default |
|
|
137
|
+
|---------| ------------|----------|
|
|
138
|
+
| `UPD2MQTT_UPDATE` | Update mode, either `Passive` or `Auto`. If `Auto`, updates will be installed automatically. | `Passive` |
|
|
139
|
+
| `UPD2MQTT_PICTURE` | URL to an icon to use in Home Assistant. | Docker logo URL |
|
|
140
|
+
| `UPD2MQTT_RELNOTES` | URL to release notes for the package. | |
|
|
141
|
+
| `UPD2MQTT_GIT_REPO_PATH` | Relative path to a local git repo if the image is built locally. | |
|
|
142
|
+
| `UPD2MQTT_IGNORE` | If set to `True`, the container will be ignored by updates2mqtt. | False |
|
|
107
143
|
|
|
108
|
-
If the package supports automated update, then *Skip* and *Install* buttons will appear on the Home Assistant
|
|
109
|
-
interface, and the package can be remotely fetched and the component restarted.
|
|
110
144
|
|
|
111
145
|
## Related Projects
|
|
112
146
|
|
|
@@ -114,6 +148,18 @@ Other apps useful for self-hosting with the help of MQTT:
|
|
|
114
148
|
|
|
115
149
|
- [psmqtt](https://github.com/eschava/psmqtt) - Report system health and metrics via MQTT
|
|
116
150
|
|
|
151
|
+
Find more at [awesome-mqtt](https://github.com/rhizomatics/awesome-mqtt)
|
|
152
|
+
|
|
117
153
|
## Development
|
|
118
154
|
|
|
119
|
-
|
|
155
|
+
This component relies on several open source packages:
|
|
156
|
+
|
|
157
|
+
- [docker-py](https://docker-py.readthedocs.io/en/stable/) SDK for Python for access to Docker APIs
|
|
158
|
+
- [Eclipse Paho](https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html) MQTT client
|
|
159
|
+
- [OmegaConf](https://omegaconf.readthedocs.io) for configuration and validation
|
|
160
|
+
- [structlog](https://www.structlog.org/en/stable/) for structured logging and [rich](https://rich.readthedocs.io/en/stable/) for better exception reporting
|
|
161
|
+
- [hishel](https://hishel.com/1.0/) for caching metadata
|
|
162
|
+
- [httpx](https://www.python-httpx.org) for retrieving metadata
|
|
163
|
+
- The Astral [uv](https://docs.astral.sh/uv/) and [ruff](https://docs.astral.sh/ruff/) tools for development and build
|
|
164
|
+
- [pytest](https://docs.pytest.org/en/stable/) and supporting add-ins for automated testing
|
|
165
|
+
- [usingversion](https://pypi.org/project/usingversion/) to log current version info
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
[](https://github.com/rhizomatics)
|
|
2
|
+
|
|
3
|
+
# updates2mqtt
|
|
4
|
+
|
|
5
|
+
[](https://github.com/rhizomatics)
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/updates2mqtt/)
|
|
8
|
+
[](https://github.com/rhizomatics/supernotify)
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
[](https://results.pre-commit.ci/latest/github/rhizomatics/updates2mqtt/main)
|
|
12
|
+
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/pypi-publish.yml)
|
|
13
|
+
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/python-package.yml)
|
|
14
|
+
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/github-code-scanning/codeql)
|
|
15
|
+
[](https://github.com/rhizomatics/updates2mqtt/actions/workflows/dependabot/dependabot-updates)
|
|
16
|
+
|
|
17
|
+
## Summary
|
|
18
|
+
|
|
19
|
+
Let Home Assistant tell you about new updates to Docker images for your containers.
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
Read the release notes, and optionally click *Update* to trigger a Docker *pull* (or optionally *build*) and *update*.
|
|
24
|
+
|
|
25
|
+
{width=480}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Description
|
|
29
|
+
|
|
30
|
+
updates2mqtt perioidically checks for new versions of components being available, and publishes new version info to MQTT. HomeAssistant auto discovery is supported, so all updates can be seen in the same place as Home Assistant's own components and add-ins.
|
|
31
|
+
|
|
32
|
+
Currently only Docker containers are supported, either via an image registry check, or a git repo for source (see [Local Builds](local_builds.md)). The design is modular, so other update sources can be added, at least for notification. The next anticipated is **apt** for Debian based systems.
|
|
33
|
+
|
|
34
|
+
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience. See [Home Assistant Integration](home_assistant.md) for details.
|
|
35
|
+
|
|
36
|
+
To get started, read the [Installation](installation.md) and [Configuration](configuration.md) pages.
|
|
37
|
+
|
|
38
|
+
For a quick spin, try this:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
docker run -e MQTT_USER=user1 -e MQTT_PASS=pass1 -e MQTT_HOST=192.168.1.5 ghcr.io/rhizomatics/updates2mqtt:release
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Release Support
|
|
45
|
+
|
|
46
|
+
Presently only Docker containers are supported, although others are planned, probably with priority for `apt`.
|
|
47
|
+
|
|
48
|
+
| Ecosystem | Support | Comments |
|
|
49
|
+
|-----------|-------------|----------------------------------------------------------------------------------------------------|
|
|
50
|
+
| Docker | Scan. Fetch | Fetch is ``docker pull`` only. Restart support only for ``docker-compose`` image based containers. |
|
|
51
|
+
|
|
52
|
+
## Healthcheck
|
|
53
|
+
|
|
54
|
+
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
|
+
|
|
56
|
+
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
|
+
|
|
58
|
+
!!! tip
|
|
59
|
+
|
|
60
|
+
Check healthcheck is working using `docker inspect --format "{{json .State.Health }}" updates2mqtt | jq`
|
|
61
|
+
|
|
62
|
+
Another approach is using a restarter service directly in Docker Compose to force a restart, in this case once a day:
|
|
63
|
+
|
|
64
|
+
```yaml title="Example Compose Service"
|
|
65
|
+
restarter:
|
|
66
|
+
image: docker:cli
|
|
67
|
+
volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
|
|
68
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart updates2mqtt; done"]
|
|
69
|
+
restart: unless-stopped
|
|
70
|
+
environment:
|
|
71
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Target Containers
|
|
75
|
+
|
|
76
|
+
While `updates2mqtt` will discover and monitor all containers running under the Docker daemon,
|
|
77
|
+
there are some options to make to those containers to tune how it works.
|
|
78
|
+
|
|
79
|
+
These happen by adding environment variables to the containers, typically inside an `.env`
|
|
80
|
+
file, or as `environment` options inside `docker-compose.yaml`.
|
|
81
|
+
|
|
82
|
+
### Automated updates
|
|
83
|
+
|
|
84
|
+
If Docker containers should be immediately updated, without any confirmation
|
|
85
|
+
or trigger, *e.g.* from the HomeAssistant update dialog, then set an environment variable `UPD2MQTT_UPDATE` in the target container to `Auto` ( it defaults to `Passive`)
|
|
86
|
+
|
|
87
|
+
```yaml title="Example Compose Snippet"
|
|
88
|
+
restarter:
|
|
89
|
+
image: docker:cli
|
|
90
|
+
command: ["/bin/sh", "-c", "while true; do sleep 86400; docker restart mailserver; done"]
|
|
91
|
+
environment:
|
|
92
|
+
- UPD2MQTT_UPDATE=AUTO
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Environment Variables
|
|
96
|
+
|
|
97
|
+
The following environment variables can be used to configure containers for `updates2mqtt`:
|
|
98
|
+
|
|
99
|
+
| Env Var | Description | Default |
|
|
100
|
+
|---------| ------------|----------|
|
|
101
|
+
| `UPD2MQTT_UPDATE` | Update mode, either `Passive` or `Auto`. If `Auto`, updates will be installed automatically. | `Passive` |
|
|
102
|
+
| `UPD2MQTT_PICTURE` | URL to an icon to use in Home Assistant. | Docker logo URL |
|
|
103
|
+
| `UPD2MQTT_RELNOTES` | URL to release notes for the package. | |
|
|
104
|
+
| `UPD2MQTT_GIT_REPO_PATH` | Relative path to a local git repo if the image is built locally. | |
|
|
105
|
+
| `UPD2MQTT_IGNORE` | If set to `True`, the container will be ignored by updates2mqtt. | False |
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## Related Projects
|
|
109
|
+
|
|
110
|
+
Other apps useful for self-hosting with the help of MQTT:
|
|
111
|
+
|
|
112
|
+
- [psmqtt](https://github.com/eschava/psmqtt) - Report system health and metrics via MQTT
|
|
113
|
+
|
|
114
|
+
Find more at [awesome-mqtt](https://github.com/rhizomatics/awesome-mqtt)
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
This component relies on several open source packages:
|
|
119
|
+
|
|
120
|
+
- [docker-py](https://docker-py.readthedocs.io/en/stable/) SDK for Python for access to Docker APIs
|
|
121
|
+
- [Eclipse Paho](https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html) MQTT client
|
|
122
|
+
- [OmegaConf](https://omegaconf.readthedocs.io) for configuration and validation
|
|
123
|
+
- [structlog](https://www.structlog.org/en/stable/) for structured logging and [rich](https://rich.readthedocs.io/en/stable/) for better exception reporting
|
|
124
|
+
- [hishel](https://hishel.com/1.0/) for caching metadata
|
|
125
|
+
- [httpx](https://www.python-httpx.org) for retrieving metadata
|
|
126
|
+
- The Astral [uv](https://docs.astral.sh/uv/) and [ruff](https://docs.astral.sh/ruff/) tools for development and build
|
|
127
|
+
- [pytest](https://docs.pytest.org/en/stable/) and supporting add-ins for automated testing
|
|
128
|
+
- [usingversion](https://pypi.org/project/usingversion/) to log current version info
|
|
@@ -1,26 +1,89 @@
|
|
|
1
|
-
|
|
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 =
|
|
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")
|