Date: Sat, 17 Aug 2024 08:50:39 -0400
Subject: [PATCH 045/218] style: Add pre-commit checks and code cleanup
This change adds an optional pre-commit configuration that can be used
to keep the code style clean. I've also run it across all files and
fixed numerous whitespaces issues.
To use it, if wanted, just clone / pull the repo as normal, go into the
folder and run:
```
pre-commit install
```
From that point on, when running `git commit`, it will run the checks
on any changed files.
Feel free to ignore this PR if you're not interested.
---
.pre-commit-config.yaml | 11 +++++++++
README.md | 20 +++++++--------
dockcheck.sh | 47 ++++++++++++++++++------------------
extras/apprise_quickstart.md | 16 ++++++------
extras/dc_brief.sh | 4 +--
extras/errorCheck.sh | 4 +--
notify_DSM.sh | 2 +-
notify_apprise.sh | 2 --
notify_gotify.sh | 10 ++++----
notify_matrix.sh | 8 +++---
notify_smtp.sh | 2 +-
notify_telegram.sh | 10 ++++----
12 files changed, 72 insertions(+), 64 deletions(-)
create mode 100644 .pre-commit-config.yaml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..04b74b8
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,11 @@
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.6.0
+ hooks:
+ - id: check-yaml
+ - id: check-added-large-files
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
+ - id: end-of-file-fixer
+ - id: mixed-line-ending
+ args: ['--fix=lf']
diff --git a/README.md b/README.md
index 02b87b5..fb62329 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-
+
@@ -72,16 +72,16 @@ Containers with updates available:
Choose what containers to update:
Enter number(s) separated by comma, [a] for all - [q] to quit:
```
-Then it proceedes to run `pull` and `up -d` on every container with updates.
+Then it proceedes to run `pull` and `up -d` on every container with updates.
After the updates are complete, you'll get prompted if you'd like to prune dangling images.
___
## :nut_and_bolt: Dependencies
-- Running docker (duh) and compose, either standalone or plugin.
+- Running docker (duh) and compose, either standalone or plugin.
- Bash shell or compatible shell of at least v4.3
-- [regclient/regctl](https://github.com/regclient/regclient) (Licensed under [Apache-2.0 License](http://www.apache.org/licenses/LICENSE-2.0))
- - User will be prompted to download `regctl` if not in `PATH` or `PWD`.
+- [regclient/regctl](https://github.com/regclient/regclient) (Licensed under [Apache-2.0 License](http://www.apache.org/licenses/LICENSE-2.0))
+ - User will be prompted to download `regctl` if not in `PATH` or `PWD`.
- regctl requires `amd64/arm64` - see [workaround](#roller_coaster-workaround-for-non-amd64--arm64) if other architecture is used.
## :tent: Install Instructions
@@ -99,10 +99,10 @@ Add preferred `notify.sh`-template to the same directory - this will not be touc
## :loudspeaker: Notifications
-Trigger with the `-i` flag.
+Trigger with the `-i` flag.
Run it scheduled with `-ni` to only get notified when there's updates available!
-Use a `notify_X.sh` template file, copy it to `notify.sh`, modify it to your needs! (notify.sh is added to .gitignore)
+Use a `notify_X.sh` template file, copy it to `notify.sh`, modify it to your needs! (notify.sh is added to .gitignore)
**Current templates:**
- Synology [DSM](https://www.synology.com/en-global/dsm)
- Email with [mSMTP](https://wiki.debian.org/msmtp) (or deprecated alternative [sSMTP](https://wiki.debian.org/sSMTP))
@@ -115,7 +115,7 @@ Use a `notify_X.sh` template file, copy it to `notify.sh`, modify it to your nee
- [Telegram](https://telegram.org/) - Telegram chat API.
- [Matrix-Synapse](https://github.com/element-hq/synapse) - [Matrix](https://matrix.org/), open, secure, decentralised communication.
-Further additions are welcome - suggestions or PR!
+Further additions are welcome - suggestions or PR!
Initiated and first contributed by [yoyoma2](https://github.com/yoyoma2).
## :bookmark: Labels
@@ -163,7 +163,7 @@ function dchk {
- Not working well with containers created by Portainer.
## :warning: `-r flag` disclaimer and warning
-**Wont auto-update the containers, only their images. (compose is recommended)**
+**Wont auto-update the containers, only their images. (compose is recommended)**
`docker run` dont support using new images just by restarting a container.
Containers need to be manually stopped, removed and created again to run on the new image.
@@ -176,5 +176,5 @@ ___
## Special Thanks
-- :bison: [t0rnis](https://github.com/t0rnis)
+- :bison: [t0rnis](https://github.com/t0rnis)
- :leopard: [Palleri](https://github.com/Palleri)
diff --git a/dockcheck.sh b/dockcheck.sh
index 3a00518..0ea7c73 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -16,7 +16,7 @@ LatestChanges="$(curl -s -r 0-200 $RawUrl | sed -n "/ChangeNotes/s/### ChangeNot
### Help Function:
Help() {
- echo "Syntax: dockcheck.sh [OPTION] [part of name to filter]"
+ echo "Syntax: dockcheck.sh [OPTION] [part of name to filter]"
echo "Example: dockcheck.sh -y -d 10 -e nextcloud,heimdall"
echo
echo "Options:"
@@ -58,7 +58,7 @@ while getopts "aynpfrhlisvme:d:t:" options; do
e) Exclude=${OPTARG} ;;
m) declare c_{red,green,yellow,blue,teal,reset}="" ;;
s) Stopped="-a" ;;
- t) Timeout="${OPTARG}" ;;
+ t) Timeout="${OPTARG}" ;;
v) printf "%s\n" "$VERSION" ; exit 0 ;;
d) DaysOld=${OPTARG}
if ! [[ $DaysOld =~ ^[0-9]+$ ]] ; then { printf "Days -d argument given (%s) is not a number.\n" "${DaysOld}" ; exit 2 ; } ; fi ;;
@@ -69,12 +69,12 @@ shift "$((OPTIND-1))"
self_update_curl() {
cp "$ScriptPath" "$ScriptPath".bak
- if [[ $(builtin type -P curl) ]]; then
- curl -L $RawUrl > "$ScriptPath" ; chmod +x "$ScriptPath"
+ if [[ $(builtin type -P curl) ]]; then
+ curl -L $RawUrl > "$ScriptPath" ; chmod +x "$ScriptPath"
printf "\n%s\n" "--- starting over with the updated version ---"
exec "$ScriptPath" "${ScriptArgs[@]}" # run the new script with old arguments
exit 1 # exit the old instance
- elif [[ $(builtin type -P wget) ]]; then
+ elif [[ $(builtin type -P wget) ]]; then
wget $RawUrl -O "$ScriptPath" ; chmod +x "$ScriptPath"
printf "\n%s\n" "--- starting over with the updated version ---"
exec "$ScriptPath" "${ScriptArgs[@]}" # run the new script with old arguments
@@ -103,7 +103,7 @@ self_update() {
choosecontainers() {
while [[ -z "$ChoiceClean" ]]; do
read -r -p "Enter number(s) separated by comma, [a] for all - [q] to quit: " Choice
- if [[ "$Choice" =~ [qQnN] ]] ; then
+ if [[ "$Choice" =~ [qQnN] ]] ; then
exit 0
elif [[ "$Choice" =~ [aAyY] ]] ; then
SelectedUpdates=( "${GotUpdates[@]}" )
@@ -147,9 +147,9 @@ progress_bar() {
}
### Version check & initiate self update
-if [[ "$VERSION" != "$LatestRelease" ]] ; then
+if [[ "$VERSION" != "$LatestRelease" ]] ; then
printf "New version available! %b%s%b ⇒ %b%s%b \n Change Notes: %s \n" "$c_yellow" "$VERSION" "$c_reset" "$c_green" "$LatestRelease" "$c_reset" "$LatestChanges"
- if [[ -z "$AutoUp" ]] ; then
+ if [[ -z "$AutoUp" ]] ; then
read -r -p "Would you like to update? y/[n]: " SelfUpdate
[[ "$SelfUpdate" =~ [yY] ]] && self_update
fi
@@ -218,7 +218,7 @@ DocCount=$(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}'
RegCheckQue=0
### Testing and setting timeout binary
-t_out=$(type -P "timeout")
+t_out=$(type -P "timeout")
if [[ $t_out ]]; then
t_out=$(realpath $t_out 2>/dev/null || readlink -f $t_out)
if [[ $t_out =~ "busybox" ]]; then
@@ -233,17 +233,17 @@ for i in $(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}')
((RegCheckQue+=1))
progress_bar "$RegCheckQue" "$DocCount"
### Looping every item over the list of excluded names and skipping:
- for e in "${Excludes[@]}" ; do [[ "$i" == "$e" ]] && continue 2 ; done
+ for e in "${Excludes[@]}" ; do [[ "$i" == "$e" ]] && continue 2 ; done
RepoUrl=$(docker inspect "$i" --format='{{.Config.Image}}')
LocalHash=$(docker image inspect "$RepoUrl" --format '{{.RepoDigests}}')
# Checking for errors while setting the variable:
if RegHash=$(${t_out} $regbin image digest --list "$RepoUrl" 2>&1) ; then
- if [[ "$LocalHash" = *"$RegHash"* ]] ; then
- NoUpdates+=("$i")
- else
+ if [[ "$LocalHash" = *"$RegHash"* ]] ; then
+ NoUpdates+=("$i")
+ else
if [[ -n "$DaysOld" ]] && ! datecheck ; then
- NoUpdates+=("+$i ${ImageAge}d")
- else
+ NoUpdates+=("+$i ${ImageAge}d")
+ else
GotUpdates+=("$i")
fi
fi
@@ -273,13 +273,13 @@ if [[ -n ${GotErrors[*]} ]] ; then
printf "%s\n" "${GotErrors[@]}"
printf "%binfo:%b 'unauthorized' often means not found in a public registry.\n" "$c_blue" "$c_reset"
fi
-if [[ -n ${GotUpdates[*]} ]] ; then
+if [[ -n ${GotUpdates[*]} ]] ; then
printf "\n%bContainers with updates available:%b\n" "$c_yellow" "$c_reset"
[[ -z "$AutoUp" ]] && options || printf "%s\n" "${GotUpdates[@]}"
[[ -n "$Notify" ]] && { [[ $(type -t send_notification) == function ]] && send_notification "${GotUpdates[@]}" || printf "Could not source notification function.\n" ; }
fi
-### Optionally get updates if there's any
+### Optionally get updates if there's any
if [ -n "$GotUpdates" ] ; then
if [ -z "$AutoUp" ] ; then
printf "\n%bChoose what containers to update.%b\n" "$c_teal" "$c_reset"
@@ -302,14 +302,14 @@ if [ -n "$GotUpdates" ] ; then
ContUpdateLabel=$(docker inspect "$i" --format '{{ index .Config.Labels "mag37.dockcheck.update" }}')
ContRestartStack=$(docker inspect "$i" --format '{{ index .Config.Labels "mag37.dockcheck.restart-stack" }}')
### Checking if compose-values are empty - hence started with docker run:
- if [ -z "$ContPath" ] ; then
+ if [ -z "$ContPath" ] ; then
if [ "$DRunUp" == "yes" ] ; then
docker pull "$ContImage"
printf "%s\n" "$i got a new image downloaded, rebuild manually with preferred 'docker run'-parameters"
else
printf "\n%b%s%b has no compose labels, probably started with docker run - %bskipping%b\n\n" "$c_yellow" "$i" "$c_reset" "$c_yellow" "$c_reset"
fi
- continue
+ continue
fi
### cd to the compose-file directory to account for people who use relative volumes, eg - ${PWD}/data:data
cd "$ContPath" || { echo "Path error - skipping $i" ; continue ; }
@@ -326,15 +326,15 @@ if [ -n "$GotUpdates" ] ; then
### Check if the container got an environment file set and reformat it
if [ -n "$ContEnv" ]; then ContEnvs=$(for env in ${ContEnv//,/ } ; do printf -- "--env-file %s " "$env"; done) ; fi
### Check if the whole stack should be restarted
- if [[ "$ContRestartStack" == true ]] || [[ "$ForceRestartStacks" == true ]] ; then
- $DockerBin ${CompleteConfs} stop ; $DockerBin ${CompleteConfs} ${ContEnvs} up -d
+ if [[ "$ContRestartStack" == true ]] || [[ "$ForceRestartStacks" == true ]] ; then
+ $DockerBin ${CompleteConfs} stop ; $DockerBin ${CompleteConfs} ${ContEnvs} up -d
else
- $DockerBin ${CompleteConfs} ${ContEnvs} up -d ${ContName}
+ $DockerBin ${CompleteConfs} ${ContEnvs} up -d ${ContName}
fi
done
printf "\n%bAll done!%b\n" "$c_green" "$c_reset"
[[ -z "$AutoPrune" ]] && read -r -p "Would you like to prune dangling images? y/[n]: " AutoPrune
- [[ "$AutoPrune" =~ [yY] ]] && docker image prune -f
+ [[ "$AutoPrune" =~ [yY] ]] && docker image prune -f
else
printf "\nNo updates installed, exiting.\n"
fi
@@ -343,4 +343,3 @@ else
fi
exit 0
-
diff --git a/extras/apprise_quickstart.md b/extras/apprise_quickstart.md
index 4ed8bfe..2d1ddd6 100644
--- a/extras/apprise_quickstart.md
+++ b/extras/apprise_quickstart.md
@@ -25,13 +25,13 @@ services:
Then browse to the webui.

Here you'll click **Configuration Manager**, read the overview and then click on **Configuration**.
-Under **Configuration** you'll craft/paste your notification config.
+Under **Configuration** you'll craft/paste your notification config.

-The simplest way is just paste the url's as is (like in the example above).
-There are many ways to customize with tags, groups, json and more. Read [caronc/apprise-api](https://github.com/caronc/apprise-api) for more info!
+The simplest way is just paste the url's as is (like in the example above).
+There are many ways to customize with tags, groups, json and more. Read [caronc/apprise-api](https://github.com/caronc/apprise-api) for more info!
-Look at the [apprise wiki: Notification Services](https://github.com/caronc/apprise/wiki) for more info about how the url syntax for different services works.
+Look at the [apprise wiki: Notification Services](https://github.com/caronc/apprise/wiki) for more info about how the url syntax for different services works.
You can also use the [caronc/apprise-api](https://github.com/caronc/apprise-api) to host the api as a frontend to an already existing **Apprise**-setup on the host.
@@ -40,7 +40,7 @@ You can also use the [caronc/apprise-api](https://github.com/caronc/apprise-api)
### Customize the **notify.sh** file.
After you're done with the setup of the container and tried your notifications, you can copy the `notify_apprise.sh` file to `notify.sh` and start editing it.
-Comment out/remove the bare metal apprise-command (starting with `apprise -vv -t...`).
+Comment out/remove the bare metal apprise-command (starting with `apprise -vv -t...`).
Uncomment and edit the `AppriseURL` variable and *curl* line
It should look something like this when curling the API:
```bash
@@ -72,11 +72,11 @@ ___
## On host installed **Apprise**
-Follow the official guide on [caronc/apprise](https://github.com/caronc/apprise)!
+Follow the official guide on [caronc/apprise](https://github.com/caronc/apprise)!
### A brief, basic "get started"
-- Install **apprise**
+- Install **apprise**
- python package `pip install apprise`
- packaged in EPEL/Fedora `dnf install apprise`
- packaged in AUR `[yay/pikaur/paru/other] apprise`
@@ -92,7 +92,7 @@ Then either source the notifications with `-c=/path/to/config/apprise` or store
- Test apprise with a single notification:
- `apprise -vv -t 'test title' -b 'test notification body' 'mailto://myemail:mypass@gmail.com'`
- Set up your notification URL's and test them.
- - Look at the [apprise wiki: Notification Services](https://github.com/caronc/apprise/wiki) for more info about how the url syntax for different services works.
+ - Look at the [apprise wiki: Notification Services](https://github.com/caronc/apprise/wiki) for more info about how the url syntax for different services works.
### When done, customize the **notify.sh** file.
After you're done with the setup of the container and tried your notifications, you can copy the `notify_apprise.sh` file to `notify.sh` and start editing it.
diff --git a/extras/dc_brief.sh b/extras/dc_brief.sh
index c188ae0..d496d06 100755
--- a/extras/dc_brief.sh
+++ b/extras/dc_brief.sh
@@ -29,7 +29,7 @@ for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
done
### Sort arrays alphabetically
-IFS=$'\n'
+IFS=$'\n'
NoUpdates=($(sort <<<"${NoUpdates[*]}"))
GotUpdates=($(sort <<<"${GotUpdates[*]}"))
GotErrors=($(sort <<<"${GotErrors[*]}"))
@@ -44,7 +44,7 @@ if [[ -n ${GotErrors[*]} ]] ; then
printf "\n\033[0;31mContainers with errors, wont get updated:\033[0m\n"
printf "%s\n" "${GotErrors[@]}"
fi
-if [[ -n ${GotUpdates[*]} ]] ; then
+if [[ -n ${GotUpdates[*]} ]] ; then
printf "\n\033[0;33mContainers with updates available:\033[0m\n"
printf "%s\n" "${GotUpdates[@]}"
fi
diff --git a/extras/errorCheck.sh b/extras/errorCheck.sh
index 30ebe52..327f454 100755
--- a/extras/errorCheck.sh
+++ b/extras/errorCheck.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
SearchName="$1"
-for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
+for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
echo "------------ $i ------------"
ContPath=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}')
[ -z "$ContPath" ] && { "$i has no compose labels - skipping" ; continue ; }
@@ -8,7 +8,7 @@ for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
ContName=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.service" }}')
ContEnv=$(docker inspect "$i" --format '{{index .Config.Labels "com.docker.compose.project.environment_file" }}')
ContImage=$(docker inspect "$i" --format='{{.Config.Image}}')
-
+
if [[ $ContConfigFile = '/'* ]] ; then
ComposeFile="$ContConfigFile"
else
diff --git a/notify_DSM.sh b/notify_DSM.sh
index b6e4df0..2affe30 100644
--- a/notify_DSM.sh
+++ b/notify_DSM.sh
@@ -9,7 +9,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n $MSMPT ] ; then
+if [ -n $MSMPT ] ; then
MAIL=$MSMTP
elif [ -n $SSMTP ] && [ -z $MAIL ] ; then
MAIL=$SSMTP
diff --git a/notify_apprise.sh b/notify_apprise.sh
index 9945524..9080cd8 100644
--- a/notify_apprise.sh
+++ b/notify_apprise.sh
@@ -33,5 +33,3 @@ apprise -vv -t "$MessageTitle" -b "$MessageBody" \
# curl -X POST -F "title=$MessageTitle" -F "body=$MessageBody" -F "tags=all" $AppriseURL
}
-
-
diff --git a/notify_gotify.sh b/notify_gotify.sh
index 7a41a77..832b387 100644
--- a/notify_gotify.sh
+++ b/notify_gotify.sh
@@ -8,18 +8,18 @@ send_notification() {
Updates=("$@")
UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
-
+
# platform specific notification code would go here
printf "\nSending Gotify notification\n"
-
+
# Setting the MessageTitle and MessageBody variable here.
MessageTitle="${FromHost} - updates available."
MessageBody="Containers on ${FromHost} with updates available: ${UpdToString}"
-
+
# Modify to fit your setup:
GotifyToken="Your Gotify token here"
- GotifyUrl="https://api.gotify/message?token=${GotifyToken}"
-
+ GotifyUrl="https://api.gotify/message?token=${GotifyToken}"
+
curl \
-F "title=${MessageTitle}" \
-F "message=${MessageBody}" \
diff --git a/notify_matrix.sh b/notify_matrix.sh
index 4c98456..998592a 100644
--- a/notify_matrix.sh
+++ b/notify_matrix.sh
@@ -8,13 +8,13 @@ send_notification() {
Updates=("$@")
UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
-
+
# platform specific notification code would go here
printf "\nSending Matrix notification\n"
-
+
# Setting the MessageBody variable here.
MessageBody="🐋 Containers on $FromHost with updates available: \n$UpdToString"
-
+
# Modify to fit your setup:
AccessToken="Your Matrix token here"
Room_id="Enter Room_id here"
@@ -24,5 +24,5 @@ send_notification() {
# URL Example: https://matrix.org/_matrix/client/r0/rooms/!xxxxxx:example.com/send/m.room.message?access_token=xxxxxxxx
curl -sS -o /dev/null --fail -X POST "$MatrixServer/_matrix/client/r0/rooms/$Room_id/send/m.room.message?access_token=$AccessToken" -H 'Content-Type: application/json' -d "$MsgBody"
-
+
}
diff --git a/notify_smtp.sh b/notify_smtp.sh
index c62d3ed..9c81aa9 100644
--- a/notify_smtp.sh
+++ b/notify_smtp.sh
@@ -8,7 +8,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n $MSMPT ] ; then
+if [ -n $MSMPT ] ; then
MAIL=$MSMTP
elif [ -n $SSMTP ] && [ -z $MAIL ] ; then
MAIL=$SSMTP
diff --git a/notify_telegram.sh b/notify_telegram.sh
index e6da963..45584e6 100644
--- a/notify_telegram.sh
+++ b/notify_telegram.sh
@@ -8,20 +8,20 @@ send_notification() {
Updates=("$@")
UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
-
+
# platform specific notification code would go here
printf "\nSending Telegram notification\n"
-
+
# Setting the MessageBody variable here.
MessageBody="🐋 Containers on $FromHost with updates available: \n$UpdToString"
-
+
# Modify to fit your setup:
TelegramToken="Your Telegram token here"
TelegramChatId="Your Telegram ChatId here"
TelegramUrl="https://api.telegram.org/bot$TelegramToken"
TelegramTopicID=12345678 ## Set to 0 if not using specific topic within chat
TelegramData="{\"chat_id\":\"$TelegramChatId\",\"text\":\"$MessageBody\",\"message_thread_id\":\"$TelegramTopicID\",\"disable_notification\": false}"
-
+
curl -sS -o /dev/null --fail -X POST "$TelegramUrl/sendMessage" -H 'Content-Type: application/json' -d "$TelegramData"
-
+
}
From 7d825f36c9ebcfbcfd01d1b1499276258bf4a969 Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 17 Aug 2024 22:56:04 +0200
Subject: [PATCH 046/218] Rewrote prune prompt logic, wont prompt if
none-interactive flags are used
---
dockcheck.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index 0ea7c73..67a7fab 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-VERSION="v0.4.7"
-### ChangeNotes: Notification template changes for: gotify(new), DSM(improved), SMTP(deprecation alternative).
+VERSION="v0.4.8"
+### ChangeNotes: Rewrote prune to not prompt (default no) if -a|-y or -n flags are used. -p will still autoprune.
Github="https://github.com/mag37/dockcheck"
RawUrl="https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh"
@@ -333,7 +333,7 @@ if [ -n "$GotUpdates" ] ; then
fi
done
printf "\n%bAll done!%b\n" "$c_green" "$c_reset"
- [[ -z "$AutoPrune" ]] && read -r -p "Would you like to prune dangling images? y/[n]: " AutoPrune
+ if [[ -z "$AutoPrune" ]] && [[ -z "$AutoUp" ]]; then read -r -p "Would you like to prune dangling images? y/[n]: " AutoPrune ; fi
[[ "$AutoPrune" =~ [yY] ]] && docker image prune -f
else
printf "\nNo updates installed, exiting.\n"
From 923736c413433de4764546516eff444284cde3be Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 17 Aug 2024 23:00:41 +0200
Subject: [PATCH 047/218] version bump+info
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index fb62329..93eaac2 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
___
## :bell: Changelog
+- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
- **v0.4.6**: Compatibility changes to timeout, due to busybox.
- **v0.4.5**: Bugfixes, compatibility changes to timeout and arrays.
From 5b31e68f73ef82513fc1239174b186b344e073c0 Mon Sep 17 00:00:00 2001
From: Joe Harrison <53116754+sudo-kraken@users.noreply.github.com>
Date: Mon, 9 Sep 2024 22:57:11 +0100
Subject: [PATCH 048/218] Create notify_pushover.sh
---
notify_pushover.sh | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 notify_pushover.sh
diff --git a/notify_pushover.sh b/notify_pushover.sh
new file mode 100644
index 0000000..805e7ec
--- /dev/null
+++ b/notify_pushover.sh
@@ -0,0 +1,32 @@
+### DISCLAIMER: This is a third party addition to dockcheck - best effort testing.
+#
+# Copy/rename this file to notify.sh to enable the notification snippet.
+# Required receiving services must already be set up.
+# Requires jq installed and in PATH.
+# Modify to fit your setup - set Url and Token.
+
+send_notification() {
+ Updates=("$@")
+ UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ FromHost=$(hostname)
+
+ # platform specific notification code would go here
+ printf "\nSending pushover notification\n"
+
+ MessageTitle="$FromHost - updates available."
+ # Setting the MessageBody variable here.
+ MessageBody="Containers on $FromHost with updates available: $UpdToString"
+
+ # Modify to fit your setup:
+ PushoverUrl="https://api.pushover.net/1/messages.json"
+ PushoverUserKey="Your Pushover User Key Here"
+ PushoverToken="Your Pushover API Token Here"
+
+ # Sending the notification via Pushover
+ curl -sS -o /dev/null --show-error --fail -X POST \
+ -F "token=$PushoverToken" \
+ -F "user=$PushoverUserKey" \
+ -F "title=$MessageTitle" \
+ -F "message=$MessageBody" \
+ $PushoverUrl
+}
From a79de24bcc517932e4f8b8d7d571c03e7d37b32a Mon Sep 17 00:00:00 2001
From: mag37
Date: Wed, 18 Sep 2024 16:44:32 +0200
Subject: [PATCH 049/218] Cleanups + info to readme
---
README.md | 20 ++++++++-----------
.../notify_DSM.sh | 0
.../notify_apprise.sh | 0
.../notify_generic.sh | 0
.../notify_gotify.sh | 0
.../notify_matrix.sh | 0
.../notify_ntfy-sh.sh | 0
.../notify_pushbullet.sh | 0
.../notify_pushover.sh | 0
.../notify_smtp.sh | 0
.../notify_telegram.sh | 0
11 files changed, 8 insertions(+), 12 deletions(-)
rename notify_DSM.sh => notify_templates/notify_DSM.sh (100%)
rename notify_apprise.sh => notify_templates/notify_apprise.sh (100%)
rename notify_generic.sh => notify_templates/notify_generic.sh (100%)
rename notify_gotify.sh => notify_templates/notify_gotify.sh (100%)
rename notify_matrix.sh => notify_templates/notify_matrix.sh (100%)
rename notify_ntfy-sh.sh => notify_templates/notify_ntfy-sh.sh (100%)
rename notify_pushbullet.sh => notify_templates/notify_pushbullet.sh (100%)
rename notify_pushover.sh => notify_templates/notify_pushover.sh (100%)
rename notify_smtp.sh => notify_templates/notify_smtp.sh (100%)
rename notify_telegram.sh => notify_templates/notify_telegram.sh (100%)
diff --git a/README.md b/README.md
index 93eaac2..e5973de 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,6 @@ ___
- **v0.4.6**: Compatibility changes to timeout, due to busybox.
- **v0.4.5**: Bugfixes, compatibility changes to timeout and arrays.
- **v0.4.3**: Added timeout option to skip container if registry check takes too long (10s default).
-- **v0.4.1**: Syntax and logic cleanups, bugfixes on multi compose and env-files.
-- **v0.4.0**: Reworked selfupdate (auto git/curl/wget), general syntax cleanup, added -v for version.
-- **v0.3.8**: Fixed `--env-file` logic to work with multiple env-files.
-- **v0.3.7**: Added support for [labels](#bookmark-labels), added the `-f` option (force restart stack).
-- **v0.3.6**: Added pushbullet template.
-- **v0.3.5**: Added a simple progress bar for the registry checkup.
___
@@ -103,7 +97,7 @@ Add preferred `notify.sh`-template to the same directory - this will not be touc
Trigger with the `-i` flag.
Run it scheduled with `-ni` to only get notified when there's updates available!
-Use a `notify_X.sh` template file, copy it to `notify.sh`, modify it to your needs! (notify.sh is added to .gitignore)
+Use a `notify_X.sh` template file from the **notify_templates** directory, copy it to `notify.sh` alongside the script, modify it to your needs! (notify.sh is added to .gitignore)
**Current templates:**
- Synology [DSM](https://www.synology.com/en-global/dsm)
- Email with [mSMTP](https://wiki.debian.org/msmtp) (or deprecated alternative [sSMTP](https://wiki.debian.org/sSMTP))
@@ -115,6 +109,7 @@ Use a `notify_X.sh` template file, copy it to `notify.sh`, modify it to your nee
- [Pushbullet](https://www.pushbullet.com/) - connecting different devices with cross-platform features.
- [Telegram](https://telegram.org/) - Telegram chat API.
- [Matrix-Synapse](https://github.com/element-hq/synapse) - [Matrix](https://matrix.org/), open, secure, decentralised communication.
+- [Pushover](https://pushover.net/) - Simple Notifications (to your phone, wearables, desktops)
Further additions are welcome - suggestions or PR!
Initiated and first contributed by [yoyoma2](https://github.com/yoyoma2).
@@ -161,13 +156,18 @@ function dchk {
## :hammer: Known issues
- No detailed error feedback (just skip + list what's skipped).
- Not respecting `--profile` options when re-creating the container.
-- Not working well with containers created by Portainer.
+- Not working well with containers created by **Portainer**.
+- **Watchtower** might cause issues due to retagging images when checking for updates (and thereby pulling new images).
## :warning: `-r flag` disclaimer and warning
**Wont auto-update the containers, only their images. (compose is recommended)**
`docker run` dont support using new images just by restarting a container.
Containers need to be manually stopped, removed and created again to run on the new image.
+## :wrench: Debugging
+If you hit issues, you could check the output of the `extras/errorCheck.sh` script for clues.
+Another option is to run the main script with debugging in a subshell `bash -x dockcheck.sh` - if there's a particular container/image that's causing issues you can filter for just that through `bash -x dockcheck.sh nginx`.
+
## :scroll: License
dockcheck is created and released under the [GNU GPL v3.0](https://www.gnu.org/licenses/gpl-3.0-standalone.html) license.
@@ -175,7 +175,3 @@ dockcheck is created and released under the [GNU GPL v3.0](https://www.gnu.org/l
___
-
-## Special Thanks
-- :bison: [t0rnis](https://github.com/t0rnis)
-- :leopard: [Palleri](https://github.com/Palleri)
diff --git a/notify_DSM.sh b/notify_templates/notify_DSM.sh
similarity index 100%
rename from notify_DSM.sh
rename to notify_templates/notify_DSM.sh
diff --git a/notify_apprise.sh b/notify_templates/notify_apprise.sh
similarity index 100%
rename from notify_apprise.sh
rename to notify_templates/notify_apprise.sh
diff --git a/notify_generic.sh b/notify_templates/notify_generic.sh
similarity index 100%
rename from notify_generic.sh
rename to notify_templates/notify_generic.sh
diff --git a/notify_gotify.sh b/notify_templates/notify_gotify.sh
similarity index 100%
rename from notify_gotify.sh
rename to notify_templates/notify_gotify.sh
diff --git a/notify_matrix.sh b/notify_templates/notify_matrix.sh
similarity index 100%
rename from notify_matrix.sh
rename to notify_templates/notify_matrix.sh
diff --git a/notify_ntfy-sh.sh b/notify_templates/notify_ntfy-sh.sh
similarity index 100%
rename from notify_ntfy-sh.sh
rename to notify_templates/notify_ntfy-sh.sh
diff --git a/notify_pushbullet.sh b/notify_templates/notify_pushbullet.sh
similarity index 100%
rename from notify_pushbullet.sh
rename to notify_templates/notify_pushbullet.sh
diff --git a/notify_pushover.sh b/notify_templates/notify_pushover.sh
similarity index 100%
rename from notify_pushover.sh
rename to notify_templates/notify_pushover.sh
diff --git a/notify_smtp.sh b/notify_templates/notify_smtp.sh
similarity index 100%
rename from notify_smtp.sh
rename to notify_templates/notify_smtp.sh
diff --git a/notify_telegram.sh b/notify_templates/notify_telegram.sh
similarity index 100%
rename from notify_telegram.sh
rename to notify_templates/notify_telegram.sh
From 640046668ccf4897c4983ced4e66e0cd6d65dffe Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 28 Sep 2024 14:22:09 +0200
Subject: [PATCH 050/218] added project url to --help
---
dockcheck.sh | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dockcheck.sh b/dockcheck.sh
index 67a7fab..77ad27f 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -34,6 +34,8 @@ Help() {
echo "-s Include stopped containers in the check. (Logic: docker ps -a)."
echo "-t Set a timeout (in seconds) per container for registry checkups, 10 is default."
echo "-v Prints current version."
+ echo
+ echo "Project source: $Github"
}
### Colors:
From 999694985a853a490cba32593c946e2e81e3f4c4 Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 28 Sep 2024 14:24:34 +0200
Subject: [PATCH 051/218] Added sponsorlist - section.
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e5973de..3c9b238 100644
--- a/README.md
+++ b/README.md
@@ -171,7 +171,11 @@ Another option is to run the main script with debugging in a subshell `bash -x d
## :scroll: License
dockcheck is created and released under the [GNU GPL v3.0](https://www.gnu.org/licenses/gpl-3.0-standalone.html) license.
-### :floppy_disk: The [story](https://mag37.org/posts/project_dockcheck/) behind it. 1 year in retrospect.
+## :heartpulse: Sponsorlist
+
+- [avegy](https://github.com/avegy)
___
+### :floppy_disk: The [story](https://mag37.org/posts/project_dockcheck/) behind it. 1 year in retrospect.
+
From 91ff4aaaa7777cccd0eacb96f8db614a95cb3bba Mon Sep 17 00:00:00 2001
From: mag37
Date: Wed, 2 Oct 2024 20:44:32 +0200
Subject: [PATCH 052/218] Added notification release notes url function
---
notify_templates/releasenotes.sh | 17 +++++++++++++++++
notify_templates/urls.list | 3 +++
2 files changed, 20 insertions(+)
create mode 100644 notify_templates/releasenotes.sh
create mode 100644 notify_templates/urls.list
diff --git a/notify_templates/releasenotes.sh b/notify_templates/releasenotes.sh
new file mode 100644
index 0000000..92fe53f
--- /dev/null
+++ b/notify_templates/releasenotes.sh
@@ -0,0 +1,17 @@
+### Snippet to use together with notify.sh
+#
+# Requires a space-separated list-file of container-name and release-note-url, modify the example file "urls.list"
+# Copy urls.list and releasenotes.sh to the same directory as dockcheck.sh.
+#
+# Add the next line (uncommented) to any notification script you're using, after the "UpdToString"-variable setup
+# [ -s "$ScriptWorkDir"/releasenotes.sh ] && { source "$ScriptWorkDir"/releasenotes.sh ; UpdToString=$( releasenotes ) ; }
+
+releasenotes() {
+ for update in ${Updates[@]}; do
+ found=false
+ while read -r container url; do
+ [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
+ done < urls.list
+ [[ $found == false ]] && printf "%s\n" "$update"
+ done
+}
diff --git a/notify_templates/urls.list b/notify_templates/urls.list
new file mode 100644
index 0000000..c8faef1
--- /dev/null
+++ b/notify_templates/urls.list
@@ -0,0 +1,3 @@
+apprise-api https://github.com/linuxserver/docker-apprise-api/releases
+homer https://github.com/bastienwirtz/homer/releases
+nginx https://github.com/docker-library/official-images/blob/master/library/nginx
From 827bb7e14acc18ac73ab5cacb471f4098a0c01fe Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 08:05:42 +0200
Subject: [PATCH 053/218] Update releasenotes.sh
added $ScriptWorkDir prefix to urls.list
---
notify_templates/releasenotes.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/notify_templates/releasenotes.sh b/notify_templates/releasenotes.sh
index 92fe53f..cce7944 100644
--- a/notify_templates/releasenotes.sh
+++ b/notify_templates/releasenotes.sh
@@ -11,7 +11,7 @@ releasenotes() {
found=false
while read -r container url; do
[[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
- done < urls.list
+ done < "$ScriptWorkDir"/urls.list
[[ $found == false ]] && printf "%s\n" "$update"
done
}
From 9f8c62ed96cdc2d71f34b219ef6519a0943c8558 Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 14:39:51 +0200
Subject: [PATCH 054/218] first tweaks for a release-notes addition
---
dockcheck.sh | 11 +++++++++++
notify_templates/notify_generic.sh | 2 +-
notify_templates/urls.list | 4 ++++
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index 77ad27f..14c5c1f 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -148,6 +148,17 @@ progress_bar() {
[[ "$QueTotal" == "$QueCurrent" ]] && printf "\r[%b%s%b] %s/%s \n" "$c_teal" "$BarComplete" "$c_reset" "$QueCurrent" "$QueTotal"
}
+### Function to add user-provided urls to releasenotes
+releasenotes() {
+ for update in ${Updates[@]}; do
+ found=false
+ while read -r container url; do
+ [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
+ done < "$ScriptWorkDir"/urls.list
+ [[ $found == false ]] && printf "%s -> no url in list\n" "$update"
+ done
+}
+
### Version check & initiate self update
if [[ "$VERSION" != "$LatestRelease" ]] ; then
printf "New version available! %b%s%b ⇒ %b%s%b \n Change Notes: %s \n" "$c_yellow" "$VERSION" "$c_reset" "$c_green" "$LatestRelease" "$c_reset" "$LatestChanges"
diff --git a/notify_templates/notify_generic.sh b/notify_templates/notify_generic.sh
index 04b508c..9ff6226 100644
--- a/notify_templates/notify_generic.sh
+++ b/notify_templates/notify_generic.sh
@@ -5,7 +5,7 @@
send_notification() {
Updates=("$@")
- UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/urls.list b/notify_templates/urls.list
index c8faef1..e131872 100644
--- a/notify_templates/urls.list
+++ b/notify_templates/urls.list
@@ -1,3 +1,7 @@
+# This is a list of container names and releasenote urls, separated by space.
+# Modify, add and (if necessary) remove to fit your needs.
+# Additions are welcome! Append your list to the git-repo, use generic names and sensible urls.
+
apprise-api https://github.com/linuxserver/docker-apprise-api/releases
homer https://github.com/bastienwirtz/homer/releases
nginx https://github.com/docker-library/official-images/blob/master/library/nginx
From db4431d40a6fe46e26f22a6a47a08379f8061d42 Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 14:48:05 +0200
Subject: [PATCH 055/218] Update dockcheck.sh
changed missing url-message.
---
dockcheck.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index 14c5c1f..0d66953 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -155,7 +155,7 @@ releasenotes() {
while read -r container url; do
[[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
done < "$ScriptWorkDir"/urls.list
- [[ $found == false ]] && printf "%s -> no url in list\n" "$update"
+ [[ $found == false ]] && printf "%s -> url missing\n" "$update"
done
}
From 0e3210b5610e843cdc1056bbdc1c12eef4c8c5d7 Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 14:55:43 +0200
Subject: [PATCH 056/218] added urls.list
Added urls.list to be ignored.
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index fd732aa..f3300e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
# ignore users custom notify.sh
/notify.sh
+/urls.list
# ignore the auto-installed regctl
regctl
From a55099465913d9f05312e4091e18c57b2d7d2518 Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 23:07:01 +0200
Subject: [PATCH 057/218] tweaks + version info
---
README.md | 14 ++++++++++++++
dockcheck.sh | 6 +++---
notify_templates/urls.list | 1 +
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 3c9b238..071c46f 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
___
## :bell: Changelog
+- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-Notifications)
- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
- **v0.4.6**: Compatibility changes to timeout, due to busybox.
@@ -114,6 +115,19 @@ Use a `notify_X.sh` template file from the **notify_templates** directory, copy
Further additions are welcome - suggestions or PR!
Initiated and first contributed by [yoyoma2](https://github.com/yoyoma2).
+### :date: Release notes addon to Notifications
+There's a function to use a lookup-file to add release note URL's to the notification message.
+Copy the notify_templates/`urls.list` file to the script directory and modify it as necessary, it will be used automatically if it's there.
+The output of the notification will look something like this:
+```
+Containers on hostname with updates available:
+apprise-api -> https://github.com/linuxserver/docker-apprise-api/releases
+homer -> https://github.com/bastienwirtz/homer/releases
+nginx -> https://github.com/docker-library/official-images/blob/master/library/nginx
+...
+```
+The `urls.list` file is just an example and I'd gladly see that people contribute back when they add their preferred URLs to their lists.
+
## :bookmark: Labels
Optionally add labels to compose-files. Currently these are the usable labels:
```
diff --git a/dockcheck.sh b/dockcheck.sh
index 0d66953..0660af5 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-VERSION="v0.4.8"
-### ChangeNotes: Rewrote prune to not prompt (default no) if -a|-y or -n flags are used. -p will still autoprune.
+VERSION="v0.4.9"
+### ChangeNotes: Added a function to enrich the notify-message with release note URLs. See README.
Github="https://github.com/mag37/dockcheck"
RawUrl="https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh"
@@ -155,7 +155,7 @@ releasenotes() {
while read -r container url; do
[[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
done < "$ScriptWorkDir"/urls.list
- [[ $found == false ]] && printf "%s -> url missing\n" "$update"
+ [[ $found == false ]] && printf "%s -> url missing\n" "$update" || continue
done
}
diff --git a/notify_templates/urls.list b/notify_templates/urls.list
index e131872..6b999b5 100644
--- a/notify_templates/urls.list
+++ b/notify_templates/urls.list
@@ -5,3 +5,4 @@
apprise-api https://github.com/linuxserver/docker-apprise-api/releases
homer https://github.com/bastienwirtz/homer/releases
nginx https://github.com/docker-library/official-images/blob/master/library/nginx
+vaultwarden-server https://github.com/dani-garcia/vaultwarden/releases
From 6de00a2b9017dff63a47a209c5a4f984bc2ab76a Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 23:07:58 +0200
Subject: [PATCH 058/218] removed releasenotes test script
---
notify_templates/releasenotes.sh | 17 -----------------
1 file changed, 17 deletions(-)
delete mode 100644 notify_templates/releasenotes.sh
diff --git a/notify_templates/releasenotes.sh b/notify_templates/releasenotes.sh
deleted file mode 100644
index cce7944..0000000
--- a/notify_templates/releasenotes.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-### Snippet to use together with notify.sh
-#
-# Requires a space-separated list-file of container-name and release-note-url, modify the example file "urls.list"
-# Copy urls.list and releasenotes.sh to the same directory as dockcheck.sh.
-#
-# Add the next line (uncommented) to any notification script you're using, after the "UpdToString"-variable setup
-# [ -s "$ScriptWorkDir"/releasenotes.sh ] && { source "$ScriptWorkDir"/releasenotes.sh ; UpdToString=$( releasenotes ) ; }
-
-releasenotes() {
- for update in ${Updates[@]}; do
- found=false
- while read -r container url; do
- [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
- done < "$ScriptWorkDir"/urls.list
- [[ $found == false ]] && printf "%s\n" "$update"
- done
-}
From 85ee721cd174f72a74122739f65ae8e25482c133 Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 23:09:45 +0200
Subject: [PATCH 059/218] typo
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 071c46f..ddef012 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
___
## :bell: Changelog
-- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-Notifications)
+- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-notifications)
- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
- **v0.4.6**: Compatibility changes to timeout, due to busybox.
From 62b52796f22d0122738a0512988093a75f22938e Mon Sep 17 00:00:00 2001
From: mag37
Date: Fri, 4 Oct 2024 23:19:41 +0200
Subject: [PATCH 060/218] removed empty lines
---
dockcheck.sh | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index 0660af5..d3f5780 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -13,7 +13,6 @@ ScriptWorkDir="$(dirname "$ScriptPath")"
LatestRelease="$(curl -s -r 0-50 $RawUrl | sed -n "/VERSION/s/VERSION=//p" | tr -d '"')"
LatestChanges="$(curl -s -r 0-200 $RawUrl | sed -n "/ChangeNotes/s/### ChangeNotes: //p")"
-
### Help Function:
Help() {
echo "Syntax: dockcheck.sh [OPTION] [part of name to filter]"
@@ -150,13 +149,13 @@ progress_bar() {
### Function to add user-provided urls to releasenotes
releasenotes() {
- for update in ${Updates[@]}; do
- found=false
- while read -r container url; do
- [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
- done < "$ScriptWorkDir"/urls.list
- [[ $found == false ]] && printf "%s -> url missing\n" "$update" || continue
- done
+ for update in ${Updates[@]}; do
+ found=false
+ while read -r container url; do
+ [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
+ done < "$ScriptWorkDir"/urls.list
+ [[ $found == false ]] && printf "%s -> url missing\n" "$update" || continue
+ done
}
### Version check & initiate self update
@@ -272,7 +271,6 @@ NoUpdates=($(sort <<<"${NoUpdates[*]}"))
GotUpdates=($(sort <<<"${GotUpdates[*]}"))
unset IFS
-
### Define how many updates are available
UpdCount="${#GotUpdates[@]}"
From 319b43bc1bd0ae6104030179d85b4081d5c82444 Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 5 Oct 2024 08:03:33 +0200
Subject: [PATCH 061/218] Added releasenotes-logic to all templates, fix to
DSM+smtp
---
notify_templates/notify_DSM.sh | 12 ++++++------
notify_templates/notify_apprise.sh | 2 +-
notify_templates/notify_gotify.sh | 2 +-
notify_templates/notify_matrix.sh | 2 +-
notify_templates/notify_ntfy-sh.sh | 2 +-
notify_templates/notify_pushbullet.sh | 2 +-
notify_templates/notify_pushover.sh | 2 +-
notify_templates/notify_smtp.sh | 12 ++++++------
notify_templates/notify_telegram.sh | 2 +-
9 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/notify_templates/notify_DSM.sh b/notify_templates/notify_DSM.sh
index 2affe30..1c74c11 100644
--- a/notify_templates/notify_DSM.sh
+++ b/notify_templates/notify_DSM.sh
@@ -9,17 +9,17 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n $MSMPT ] ; then
- MAIL=$MSMTP
-elif [ -n $SSMTP ] && [ -z $MAIL ] ; then
- MAIL=$SSMTP
+if [ -n "$MSMPT" ] ; then
+ MailPkg=$MSMTP
+elif [ -n "$SSMTP" ] ; then
+ MailPkg=$SSMTP
else
echo "No msmtp or ssmtp binary found in PATH: $PATH" ; exit 1
fi
send_notification() {
Updates=("$@")
-UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
CfgFile="/usr/syno/etc/synosmtp.conf"
@@ -36,7 +36,7 @@ SenderMail=${SenderMail:-$(grep 'eventmail1' $CfgFile | sed -n 's/.*"\([^"]*\)".
printf "\nSending email notification.\n"
-$MAIL $SendMailTo << __EOF
+$MailPkg $SendMailTo << __EOF
From: "$SenderName" <$SenderMail>
date:$(date -R)
To: <$SendMailTo>
diff --git a/notify_templates/notify_apprise.sh b/notify_templates/notify_apprise.sh
index 9080cd8..b3c0219 100644
--- a/notify_templates/notify_apprise.sh
+++ b/notify_templates/notify_apprise.sh
@@ -6,7 +6,7 @@
send_notification() {
Updates=("$@")
-UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending Apprise notification\n"
diff --git a/notify_templates/notify_gotify.sh b/notify_templates/notify_gotify.sh
index 832b387..5590ea2 100644
--- a/notify_templates/notify_gotify.sh
+++ b/notify_templates/notify_gotify.sh
@@ -6,7 +6,7 @@
send_notification() {
Updates=("$@")
- UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/notify_matrix.sh b/notify_templates/notify_matrix.sh
index 998592a..b9af93a 100644
--- a/notify_templates/notify_matrix.sh
+++ b/notify_templates/notify_matrix.sh
@@ -6,7 +6,7 @@
send_notification() {
Updates=("$@")
- UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/notify_ntfy-sh.sh b/notify_templates/notify_ntfy-sh.sh
index a388b02..dc9ded7 100644
--- a/notify_templates/notify_ntfy-sh.sh
+++ b/notify_templates/notify_ntfy-sh.sh
@@ -6,7 +6,7 @@
send_notification() {
Updates=("$@")
-UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending ntfy.sh notification\n"
diff --git a/notify_templates/notify_pushbullet.sh b/notify_templates/notify_pushbullet.sh
index 9019017..c422ad8 100644
--- a/notify_templates/notify_pushbullet.sh
+++ b/notify_templates/notify_pushbullet.sh
@@ -7,7 +7,7 @@
send_notification() {
Updates=("$@")
-UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/notify_pushover.sh b/notify_templates/notify_pushover.sh
index 805e7ec..85182b8 100644
--- a/notify_templates/notify_pushover.sh
+++ b/notify_templates/notify_pushover.sh
@@ -7,7 +7,7 @@
send_notification() {
Updates=("$@")
- UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/notify_smtp.sh b/notify_templates/notify_smtp.sh
index 9c81aa9..8ae8bec 100644
--- a/notify_templates/notify_smtp.sh
+++ b/notify_templates/notify_smtp.sh
@@ -8,17 +8,17 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n $MSMPT ] ; then
- MAIL=$MSMTP
-elif [ -n $SSMTP ] && [ -z $MAIL ] ; then
- MAIL=$SSMTP
+if [ -n "$MSMPT" ] ; then
+ MailPkg=$MSMTP
+elif [ -n "$SSMTP" ] ; then
+ MailPkg=$SSMTP
else
echo "No msmtp or ssmtp binary found in PATH: $PATH" ; exit 1
fi
send_notification() {
Updates=("$@")
-UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# User variables:
@@ -28,7 +28,7 @@ SubjectTag="dockcheck"
printf "\nSending email notification.\n"
-$MAIL $SendMailTo << __EOF
+$MailPkg $SendMailTo << __EOF
From: "$FromHost" <$SendMailFrom>
date:$(date -R)
To: <$SendMailTo>
diff --git a/notify_templates/notify_telegram.sh b/notify_templates/notify_telegram.sh
index 45584e6..6183ccb 100644
--- a/notify_templates/notify_telegram.sh
+++ b/notify_templates/notify_telegram.sh
@@ -6,7 +6,7 @@
send_notification() {
Updates=("$@")
- UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
From 04b0c463665a5f5b9c3af5f4017d61349b2b899f Mon Sep 17 00:00:00 2001
From: lpukatch
Date: Sat, 5 Oct 2024 09:36:06 -0400
Subject: [PATCH 062/218] add release note urls for popular services
---
notify_templates/urls.list | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/notify_templates/urls.list b/notify_templates/urls.list
index 6b999b5..f580cc7 100644
--- a/notify_templates/urls.list
+++ b/notify_templates/urls.list
@@ -6,3 +6,29 @@ apprise-api https://github.com/linuxserver/docker-apprise-api/releases
homer https://github.com/bastienwirtz/homer/releases
nginx https://github.com/docker-library/official-images/blob/master/library/nginx
vaultwarden-server https://github.com/dani-garcia/vaultwarden/releases
+actual_server https://actualbudget.org/blog
+gotify https://github.com/gotify/server/releases
+traefik https://github.com/traefik/traefik/releases
+caddy https://github.com/caddyserver/caddy/releases
+
+calibre https://github.com/linuxserver/docker-calibre/releases
+calibre-web https://github.com/linuxserver/docker-calibre-web/releases
+readarr https://github.com/Readarr/Readarr/releases
+audiobookshelf https://github.com/advplyr/audiobookshelf/releases
+
+gluetun https://github.com/qdm12/gluetun/releases
+bazarr https://github.com/morpheus65535/bazarr/releases
+bazarr-ls https://github.com/linuxserver/docker-bazarr/releases
+prowlarr https://github.com/Prowlarr/Prowlarr/releases
+prowlarr-ls https://github.com/linuxserver/docker-prowlarr/releases
+recyclarr https://github.com/recyclarr/recyclarr/releases
+sabnzbd https://github.com/linuxserver/docker-sabnzbd
+sonarr https://github.com/linuxserver/docker-sonarr/releases
+radarr https://github.com/linuxserver/docker-radarr/releases
+lidarr https://github.com/linuxserver/docker-lidarr/releases
+jellyseerr https://github.com/Fallenbagel/jellyseerr/releases
+jellyfin https://github.com/jellyfin/jellyfin/releases
+
+home-assistant https://github.com/home-assistant/docker/releases
+zigbee2mqtt https://github.com/Koenkk/zigbee2mqtt/releases
+mqtt https://github.com/eclipse/mosquitto/tags
From 8a6a1fbec2101e1e341e5f15b2fe2e38ee6bdc3e Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 5 Oct 2024 21:26:07 +0200
Subject: [PATCH 063/218] Update urls.list
---
notify_templates/urls.list | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/notify_templates/urls.list b/notify_templates/urls.list
index f580cc7..4195632 100644
--- a/notify_templates/urls.list
+++ b/notify_templates/urls.list
@@ -22,7 +22,7 @@ bazarr-ls https://github.com/linuxserver/docker-bazarr/releases
prowlarr https://github.com/Prowlarr/Prowlarr/releases
prowlarr-ls https://github.com/linuxserver/docker-prowlarr/releases
recyclarr https://github.com/recyclarr/recyclarr/releases
-sabnzbd https://github.com/linuxserver/docker-sabnzbd
+sabnzbd https://github.com/linuxserver/docker-sabnzbd/releases
sonarr https://github.com/linuxserver/docker-sonarr/releases
radarr https://github.com/linuxserver/docker-radarr/releases
lidarr https://github.com/linuxserver/docker-lidarr/releases
From ac10a96cc821f8fb7051fda25b1ea3abcf5a9406 Mon Sep 17 00:00:00 2001
From: mag37
Date: Mon, 7 Oct 2024 21:28:31 +0200
Subject: [PATCH 064/218] all template rewritten, some guesswork
---
notify_templates/notify_DSM.sh | 4 ++--
notify_templates/notify_apprise.sh | 11 +++--------
notify_templates/notify_generic.sh | 8 +++++---
notify_templates/notify_gotify.sh | 6 +++---
notify_templates/notify_matrix.sh | 4 ++--
notify_templates/notify_ntfy-sh.sh | 11 +++--------
notify_templates/notify_pushbullet.sh | 6 +++---
notify_templates/notify_pushover.sh | 6 +++---
notify_templates/notify_smtp.sh | 4 ++--
notify_templates/notify_telegram.sh | 4 ++--
10 files changed, 28 insertions(+), 36 deletions(-)
diff --git a/notify_templates/notify_DSM.sh b/notify_templates/notify_DSM.sh
index 1c74c11..84ba7e9 100644
--- a/notify_templates/notify_DSM.sh
+++ b/notify_templates/notify_DSM.sh
@@ -18,8 +18,8 @@ else
fi
send_notification() {
-Updates=("$@")
-[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
CfgFile="/usr/syno/etc/synosmtp.conf"
diff --git a/notify_templates/notify_apprise.sh b/notify_templates/notify_apprise.sh
index b3c0219..74a6cb5 100644
--- a/notify_templates/notify_apprise.sh
+++ b/notify_templates/notify_apprise.sh
@@ -5,20 +5,15 @@
# Modify to fit your setup - if API, set AppriseURL to your Apprise ip/domain.
send_notification() {
-Updates=("$@")
-[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending Apprise notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-read -d '\n' MessageBody << __EOF
-Containers on $FromHost with updates available:
-
-$UpdToString
-
-__EOF
+MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
# Modify to fit your setup:
apprise -vv -t "$MessageTitle" -b "$MessageBody" \
diff --git a/notify_templates/notify_generic.sh b/notify_templates/notify_generic.sh
index 9ff6226..e74d806 100644
--- a/notify_templates/notify_generic.sh
+++ b/notify_templates/notify_generic.sh
@@ -4,11 +4,13 @@
# generic sample, the "Hello World" of notification addons
send_notification() {
- Updates=("$@")
- [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
+
FromHost=$(hostname)
# platform specific notification code would go here
printf "\n%bGeneric notification addon:%b" "$c_green" "$c_reset"
- printf "\nThe following docker containers on %s need to be updated:\n%s\n" "$FromHost" "$UpdToString"
+ printf "\nThe following docker containers on %s need to be updated:\n" "$FromHost"
+ printf "$UpdToString"
}
diff --git a/notify_templates/notify_gotify.sh b/notify_templates/notify_gotify.sh
index 5590ea2..0b22cbc 100644
--- a/notify_templates/notify_gotify.sh
+++ b/notify_templates/notify_gotify.sh
@@ -5,8 +5,8 @@
# Modify to fit your setup - set GotifyUrl and GotifyToken.
send_notification() {
- Updates=("$@")
- [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -14,7 +14,7 @@ send_notification() {
# Setting the MessageTitle and MessageBody variable here.
MessageTitle="${FromHost} - updates available."
- MessageBody="Containers on ${FromHost} with updates available: ${UpdToString}"
+ MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
# Modify to fit your setup:
GotifyToken="Your Gotify token here"
diff --git a/notify_templates/notify_matrix.sh b/notify_templates/notify_matrix.sh
index b9af93a..acbcb34 100644
--- a/notify_templates/notify_matrix.sh
+++ b/notify_templates/notify_matrix.sh
@@ -5,8 +5,8 @@
# Modify to fit your setup - set MatrixServer, Room_id and AccessToken
send_notification() {
- Updates=("$@")
- [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
diff --git a/notify_templates/notify_ntfy-sh.sh b/notify_templates/notify_ntfy-sh.sh
index dc9ded7..7126c63 100644
--- a/notify_templates/notify_ntfy-sh.sh
+++ b/notify_templates/notify_ntfy-sh.sh
@@ -5,20 +5,15 @@
# Use your unique Topic Name in the URL below.
send_notification() {
-Updates=("$@")
-[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending ntfy.sh notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-read -d '\n' MessageBody << __EOF
-Containers on $FromHost with updates available:
-
-$UpdToString
-
-__EOF
+MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
# Modify to fit your setup:
NtfyUrl="ntfy.sh/YourUniqueTopicName"
diff --git a/notify_templates/notify_pushbullet.sh b/notify_templates/notify_pushbullet.sh
index c422ad8..3f181a2 100644
--- a/notify_templates/notify_pushbullet.sh
+++ b/notify_templates/notify_pushbullet.sh
@@ -6,8 +6,8 @@
# Modify to fit your setup - set Url and Token.
send_notification() {
-Updates=("$@")
-[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -15,7 +15,7 @@ printf "\nSending pushbullet notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-MessageBody="Containers on $FromHost with updates available: $UpdToString"
+MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
# Modify to fit your setup:
PushUrl="https://api.pushbullet.com/v2/pushes"
diff --git a/notify_templates/notify_pushover.sh b/notify_templates/notify_pushover.sh
index 85182b8..15a491a 100644
--- a/notify_templates/notify_pushover.sh
+++ b/notify_templates/notify_pushover.sh
@@ -6,8 +6,8 @@
# Modify to fit your setup - set Url and Token.
send_notification() {
- Updates=("$@")
- [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -15,7 +15,7 @@ send_notification() {
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
- MessageBody="Containers on $FromHost with updates available: $UpdToString"
+ MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
# Modify to fit your setup:
PushoverUrl="https://api.pushover.net/1/messages.json"
diff --git a/notify_templates/notify_smtp.sh b/notify_templates/notify_smtp.sh
index 8ae8bec..5b110c7 100644
--- a/notify_templates/notify_smtp.sh
+++ b/notify_templates/notify_smtp.sh
@@ -17,8 +17,8 @@ else
fi
send_notification() {
-Updates=("$@")
-[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# User variables:
diff --git a/notify_templates/notify_telegram.sh b/notify_templates/notify_telegram.sh
index 6183ccb..4772149 100644
--- a/notify_templates/notify_telegram.sh
+++ b/notify_templates/notify_telegram.sh
@@ -5,8 +5,8 @@
# Modify to fit your setup - set TelegramChatId and TelegramToken.
send_notification() {
- Updates=("$@")
- [ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
From 87f1886d28c809d20fa59ef087e92efdb31117c0 Mon Sep 17 00:00:00 2001
From: mag37
Date: Mon, 7 Oct 2024 21:29:49 +0200
Subject: [PATCH 065/218] releasenotes rewritten to array
---
dockcheck.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index d3f5780..d15c335 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -149,12 +149,12 @@ progress_bar() {
### Function to add user-provided urls to releasenotes
releasenotes() {
- for update in ${Updates[@]}; do
+ for update in ${GotUpdates[@]}; do
found=false
while read -r container url; do
- [[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
+ [[ $update == $container ]] && Updates+=("$update -> $url") && found=true
done < "$ScriptWorkDir"/urls.list
- [[ $found == false ]] && printf "%s -> url missing\n" "$update" || continue
+ [[ $found == false ]] && Updates+=("$update -> url missing") || continue
done
}
From cb73025a614a0f2526c3f810e6526d0bf78a543b Mon Sep 17 00:00:00 2001
From: mag37
Date: Mon, 7 Oct 2024 21:31:33 +0200
Subject: [PATCH 066/218] added discord template
---
notify_templates/notify_discord.sh | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 notify_templates/notify_discord.sh
diff --git a/notify_templates/notify_discord.sh b/notify_templates/notify_discord.sh
new file mode 100644
index 0000000..9bbf64b
--- /dev/null
+++ b/notify_templates/notify_discord.sh
@@ -0,0 +1,25 @@
+### DISCLAIMER: This is a third party addition to dockcheck - best effort testing.
+#
+# Copy/rename this file to notify.sh to enable the notification snippet.
+# Required receiving services must already be set up.
+# Modify to fit your setup - set DiscordWebhookUrl
+
+send_notification() {
+ [ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
+ UpdToString=$( printf '%s\\n' "${Updates[@]}" )
+
+ echo "$UpdToString"
+ FromHost=$(hostname)
+
+ # platform specific notification code would go here
+ printf "\nSending Discord notification\n"
+
+ # Setting the MessageBody variable here.
+ MessageBody="🐋 Containers on $FromHost with updates available: \n$UpdToString"
+
+ # Modify to fit your setup:
+ DiscordWebhookUrl="PasteYourFullDiscordWebhookURL"
+
+ MsgBody="{\"username\":\"$FromHost\",\"content\":\"$MessageBody\"}"
+ curl -sS -o /dev/null --fail -X POST -H "Content-Type: application/json" -d "$MsgBody" "$DiscordWebhookUrl"
+
From 071fa4b24546a3a8b8c28ffd155ad610bdc68817 Mon Sep 17 00:00:00 2001
From: mag37
Date: Tue, 8 Oct 2024 09:41:32 +0200
Subject: [PATCH 067/218] changed regctl verbosity
---
dockcheck.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index d15c335..83a5998 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -126,7 +126,7 @@ choosecontainers() {
}
datecheck() {
- ImageDate=$($regbin image inspect "$RepoUrl" --format='{{.Created}}' | cut -d" " -f1 )
+ ImageDate=$($regbin -v error image inspect "$RepoUrl" --format='{{.Created}}' | cut -d" " -f1 )
ImageAge=$(( ( $(date +%s) - $(date -d "$ImageDate" +%s) )/86400 ))
if [ "$ImageAge" -gt "$DaysOld" ] ; then
return 0
@@ -249,7 +249,7 @@ for i in $(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}')
RepoUrl=$(docker inspect "$i" --format='{{.Config.Image}}')
LocalHash=$(docker image inspect "$RepoUrl" --format '{{.RepoDigests}}')
# Checking for errors while setting the variable:
- if RegHash=$(${t_out} $regbin image digest --list "$RepoUrl" 2>&1) ; then
+ if RegHash=$(${t_out} $regbin -v error image digest --list "$RepoUrl" 2>&1) ; then
if [[ "$LocalHash" = *"$RegHash"* ]] ; then
NoUpdates+=("$i")
else
From e0d66cc77369a2d4d92c0f9394cf290ef001422a Mon Sep 17 00:00:00 2001
From: Thomas McWork
Date: Tue, 8 Oct 2024 21:57:23 +0200
Subject: [PATCH 068/218] fix upgly typo which prevents email notifications
---
notify_templates/notify_smtp.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/notify_templates/notify_smtp.sh b/notify_templates/notify_smtp.sh
index 8ae8bec..c6f3ba2 100644
--- a/notify_templates/notify_smtp.sh
+++ b/notify_templates/notify_smtp.sh
@@ -8,7 +8,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n "$MSMPT" ] ; then
+if [ -n "$MSMTP" ] ; then
MailPkg=$MSMTP
elif [ -n "$SSMTP" ] ; then
MailPkg=$SSMTP
From 76d2921719ddca02366053f9b368a958d37e6a7c Mon Sep 17 00:00:00 2001
From: mag37
Date: Thu, 10 Oct 2024 09:48:41 +0200
Subject: [PATCH 069/218] fixed MSMTP-typo
---
notify_templates/notify_DSM.sh | 2 +-
notify_templates/notify_smtp.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/notify_templates/notify_DSM.sh b/notify_templates/notify_DSM.sh
index 84ba7e9..4285481 100644
--- a/notify_templates/notify_DSM.sh
+++ b/notify_templates/notify_DSM.sh
@@ -9,7 +9,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n "$MSMPT" ] ; then
+if [ -n "$MSMTP" ] ; then
MailPkg=$MSMTP
elif [ -n "$SSMTP" ] ; then
MailPkg=$SSMTP
diff --git a/notify_templates/notify_smtp.sh b/notify_templates/notify_smtp.sh
index 5b110c7..d8f188f 100644
--- a/notify_templates/notify_smtp.sh
+++ b/notify_templates/notify_smtp.sh
@@ -8,7 +8,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
-if [ -n "$MSMPT" ] ; then
+if [ -n "$MSMTP" ] ; then
MailPkg=$MSMTP
elif [ -n "$SSMTP" ] ; then
MailPkg=$SSMTP
From fc47b1313b295d1809c0cdfb3150bb41bf716409 Mon Sep 17 00:00:00 2001
From: mag37
Date: Thu, 10 Oct 2024 10:22:17 +0200
Subject: [PATCH 070/218] finalizing formatting and edits
---
dockcheck.sh | 2 +-
notify_templates/notify_DSM.sh | 7 +++----
notify_templates/notify_apprise.sh | 2 +-
notify_templates/notify_gotify.sh | 2 +-
notify_templates/notify_ntfy-sh.sh | 2 +-
notify_templates/notify_pushbullet.sh | 2 +-
notify_templates/notify_pushover.sh | 2 +-
notify_templates/notify_smtp.sh | 6 +++---
8 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/dockcheck.sh b/dockcheck.sh
index 83a5998..dda9efc 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -152,7 +152,7 @@ releasenotes() {
for update in ${GotUpdates[@]}; do
found=false
while read -r container url; do
- [[ $update == $container ]] && Updates+=("$update -> $url") && found=true
+ [[ $update == $container ]] && Updates+=("$update -> $url") && found=true
done < "$ScriptWorkDir"/urls.list
[[ $found == false ]] && Updates+=("$update -> url missing") || continue
done
diff --git a/notify_templates/notify_DSM.sh b/notify_templates/notify_DSM.sh
index 4285481..d9a0cd9 100644
--- a/notify_templates/notify_DSM.sh
+++ b/notify_templates/notify_DSM.sh
@@ -36,6 +36,8 @@ SenderMail=${SenderMail:-$(grep 'eventmail1' $CfgFile | sed -n 's/.*"\([^"]*\)".
printf "\nSending email notification.\n"
+printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n\n$UpdToString"
+
$MailPkg $SendMailTo << __EOF
From: "$SenderName" <$SenderMail>
date:$(date -R)
@@ -44,10 +46,7 @@ Subject: $SubjectTag Updates available on $FromHost
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
-The following containers on $FromHost have updates available:
-
-$UpdToString
-
+$MessageBody
From $SenderName
__EOF
}
diff --git a/notify_templates/notify_apprise.sh b/notify_templates/notify_apprise.sh
index 74a6cb5..8663d43 100644
--- a/notify_templates/notify_apprise.sh
+++ b/notify_templates/notify_apprise.sh
@@ -13,7 +13,7 @@ printf "\nSending Apprise notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
+printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
apprise -vv -t "$MessageTitle" -b "$MessageBody" \
diff --git a/notify_templates/notify_gotify.sh b/notify_templates/notify_gotify.sh
index 0b22cbc..b88f597 100644
--- a/notify_templates/notify_gotify.sh
+++ b/notify_templates/notify_gotify.sh
@@ -14,7 +14,7 @@ send_notification() {
# Setting the MessageTitle and MessageBody variable here.
MessageTitle="${FromHost} - updates available."
- MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
+ printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
GotifyToken="Your Gotify token here"
diff --git a/notify_templates/notify_ntfy-sh.sh b/notify_templates/notify_ntfy-sh.sh
index 7126c63..867dcaa 100644
--- a/notify_templates/notify_ntfy-sh.sh
+++ b/notify_templates/notify_ntfy-sh.sh
@@ -13,7 +13,7 @@ printf "\nSending ntfy.sh notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
+printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
NtfyUrl="ntfy.sh/YourUniqueTopicName"
diff --git a/notify_templates/notify_pushbullet.sh b/notify_templates/notify_pushbullet.sh
index 3f181a2..a07b604 100644
--- a/notify_templates/notify_pushbullet.sh
+++ b/notify_templates/notify_pushbullet.sh
@@ -15,7 +15,7 @@ printf "\nSending pushbullet notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
-MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
+printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
PushUrl="https://api.pushbullet.com/v2/pushes"
diff --git a/notify_templates/notify_pushover.sh b/notify_templates/notify_pushover.sh
index 15a491a..51cf036 100644
--- a/notify_templates/notify_pushover.sh
+++ b/notify_templates/notify_pushover.sh
@@ -15,7 +15,7 @@ send_notification() {
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
- MessageBody=$(printf "🐋 Containers on $FromHost with updates available: \n$UpdToString")
+ printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
PushoverUrl="https://api.pushover.net/1/messages.json"
diff --git a/notify_templates/notify_smtp.sh b/notify_templates/notify_smtp.sh
index d8f188f..4d98afd 100644
--- a/notify_templates/notify_smtp.sh
+++ b/notify_templates/notify_smtp.sh
@@ -28,6 +28,8 @@ SubjectTag="dockcheck"
printf "\nSending email notification.\n"
+printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n\n$UpdToString"
+
$MailPkg $SendMailTo << __EOF
From: "$FromHost" <$SendMailFrom>
date:$(date -R)
@@ -36,9 +38,7 @@ Subject: [$SubjectTag] Updates available on $FromHost
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
-The following containers on $FromHost have updates available:
-
-$UpdToString
+$MessageBody
__EOF
}
From 6db92be627a665a8240493c3d9a29137dfbd0354 Mon Sep 17 00:00:00 2001
From: mag37
Date: Sat, 12 Oct 2024 13:13:11 +0200
Subject: [PATCH 071/218] getting ready for merge
---
README.md | 5 ++++-
dockcheck.sh | 4 ++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index ddef012..2a129f3 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,9 @@
___
## :bell: Changelog
+- **v0.5.0**: Rewritten notify logic - all templates are adjusted and should be migrated to.
+ - Copy the custom settings from your current template to the new version of the same template.
+ - Look into, copy and customize the `urls.list` file if that's of interest.
- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-notifications)
- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
@@ -117,7 +120,7 @@ Further additions are welcome - suggestions or PR!
### :date: Release notes addon to Notifications
There's a function to use a lookup-file to add release note URL's to the notification message.
-Copy the notify_templates/`urls.list` file to the script directory and modify it as necessary, it will be used automatically if it's there.
+Copy the notify_templates/`urls.list` file to the script directory, it will be used automatically if it's there. Modify it as necessary, the names of interest in the left column needs to match your container names.
The output of the notification will look something like this:
```
Containers on hostname with updates available:
diff --git a/dockcheck.sh b/dockcheck.sh
index dda9efc..ffb7a21 100755
--- a/dockcheck.sh
+++ b/dockcheck.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-VERSION="v0.4.9"
-### ChangeNotes: Added a function to enrich the notify-message with release note URLs. See README.
+VERSION="v0.5.0"
+### ChangeNotes: Rewritten notify logic - all templates adjusted, transfer your current settings to a new template! See README.
Github="https://github.com/mag37/dockcheck"
RawUrl="https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh"
From 18e467274e51b63c802a7af0797dd78edf41b43c Mon Sep 17 00:00:00 2001
From: mag37
Date: Sun, 13 Oct 2024 17:11:10 +0200
Subject: [PATCH 072/218] edited changenotes
---
README.md | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2a129f3..ab1d4da 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,12 @@
___
## :bell: Changelog
-- **v0.5.0**: Rewritten notify logic - all templates are adjusted and should be migrated to.
+- **v0.5.0**: Rewritten notify logic - all templates are adjusted and should be migrated!
- Copy the custom settings from your current template to the new version of the same template.
- Look into, copy and customize the `urls.list` file if that's of interest.
+ - Other changes:
+ - Added Discord notify template.
+ - Verbosity changed of `regctl`.
- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-notifications)
- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
From 119932aa194725130507d0b8ccba19ad6f135129 Mon Sep 17 00:00:00 2001
From: mag37
Date: Sun, 13 Oct 2024 22:28:39 +0200
Subject: [PATCH 073/218] Update README.md
added Discord to the notifications list.
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index ab1d4da..db5103a 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,7 @@ Use a `notify_X.sh` template file from the **notify_templates** directory, copy
- [Telegram](https://telegram.org/) - Telegram chat API.
- [Matrix-Synapse](https://github.com/element-hq/synapse) - [Matrix](https://matrix.org/), open, secure, decentralised communication.
- [Pushover](https://pushover.net/) - Simple Notifications (to your phone, wearables, desktops)
+- [Discord](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) - Discord webhooks.
Further additions are welcome - suggestions or PR!
Initiated and first contributed by [yoyoma2](https://github.com/yoyoma2).
From ec068dd19abc5263d14f868bc6b513d99a46090c Mon Sep 17 00:00:00 2001
From: mag37
Date: Mon, 14 Oct 2024 06:28:35 +0200
Subject: [PATCH 074/218] Fixed typo.
---
notify_templates/notify_discord.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/notify_templates/notify_discord.sh b/notify_templates/notify_discord.sh
index 9bbf64b..b29966a 100644
--- a/notify_templates/notify_discord.sh
+++ b/notify_templates/notify_discord.sh
@@ -21,5 +21,8 @@ send_notification() {
DiscordWebhookUrl="PasteYourFullDiscordWebhookURL"
MsgBody="{\"username\":\"$FromHost\",\"content\":\"$MessageBody\"}"
+
curl -sS -o /dev/null --fail -X POST -H "Content-Type: application/json" -d "$MsgBody" "$DiscordWebhookUrl"
+}
+
From 8d39e1b66b74437979a49c69298d4a8f7f257d4c Mon Sep 17 00:00:00 2001
From: mag37
Date: Mon, 21 Oct 2024 20:51:23 +0200
Subject: [PATCH 075/218] new example-file
---
extras/example.gif | Bin 413916 -> 483412 bytes
extras/example_old.gif | Bin 0 -> 413916 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 extras/example_old.gif
diff --git a/extras/example.gif b/extras/example.gif
index c0da81ef56fdb00ae84e4ab2d8c9b0c0ccb6af07..82acb5a76f0d7c61a8000ea1fffaefa119f29b9b 100644
GIT binary patch
literal 483412
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