Repository: containrrr/watchtower (go)

Issue:
Crash when shoutrrr notifications are enabled but no URLs are specified
**Describe the bug**
I updated to the latest version 1.2.1 but I am getting the following error 

```
2021-03-29T08:52:34.143334096Z panic: runtime error: slice bounds out of range [:-2]
2021-03-29T08:52:34.143475927Z 
2021-03-29T08:52:34.143505723Z goroutine 1 [running]:
2021-03-29T08:52:34.143551278Z github.com/containrrr/watchtower/pkg/notifications.(*Notifier).String(0x1585d30, 0x775a08, 0x16)
2021-03-29T08:52:34.143581778Z 	/home/runner/work/watchtower/watchtower/pkg/notifications/notifier.go:61 +0x264
2021-03-29T08:52:34.143646833Z github.com/containrrr/watchtower/cmd.writeStartupMessage(0x15ba580, 0x0, 0x0, 0xd7f48b30, 0xe, 0xbfd670, 0x7924d0, 0x3f)
2021-03-29T08:52:34.143676555Z 	/home/runner/work/watchtower/watchtower/cmd/root.go:244 +0xd8
2021-03-29T08:52:34.143720702Z github.com/containrrr/watchtower/cmd.runUpgradesOnSchedule(0x15ba580, 0x1703698, 0x7924d0, 0x3f, 0x0, 0x0)
2021-03-29T08:52:34.143765924Z 	/home/runner/work/watchtower/watchtower/cmd/root.go:282 +0x1a0
2021-03-29T08:52:34.143810090Z github.com/containrrr/watchtower/cmd.Run(0x15ba580, 0xc0f744, 0x0, 0x0)
2021-03-29T08:52:34.143837127Z 	/home/runner/work/watchtower/watchtower/cmd/root.go:188 +0x2c8
2021-03-29T08:52:34.143912329Z github.com/spf13/cobra.(*Command).execute(0x15ba580, 0x140e0f8, 0x0, 0x0, 0x15ba580, 0x140e0f8)
2021-03-29T08:52:34.143937514Z 	/home/runner/go/pkg/mod/github.com/spf13/cobra@v0.0.7/command.go:842 +0x1e8
2021-03-29T08:52:34.143989384Z github.com/spf13/cobra.(*Command).ExecuteC(0x15ba580, 0x1458070, 0x0, 0x0)
2021-03-29T08:52:34.144016939Z 	/home/runner/go/pkg/mod/github.com/spf13/cobra@v0.0.7/command.go:943 +0x250
2021-03-29T08:52:34.144061124Z github.com/spf13/cobra.(*Command).Execute(...)
2021-03-29T08:52:34.144087901Z 	/home/runner/go/pkg/mod/github.com/spf13/cobra@v0.0.7/command.go:883
2021-03-29T08:52:34.144112697Z github.com/containrrr/watchtower/cmd.Execute()
2021-03-29T08:52:34.144156271Z 	/home/runner/work/watchtower/watchtower/cmd/root.go:70 +0x20
2021-03-29T08:52:34.144182493Z main.main()
2021-03-29T08:52:34.144223140Z 	/home/runner/work/watchtower/watchtower/main.go:13 +0x14
```
here is my docker compose file

```
watchtower:
   image: containrrr/watchtower:armhf-latest
   hostname: ${DOCKERHOSTNAME}
   container_name: watchtower
   environment:
     - REPO_PASS=${WATCHTOWER_REPO_PASS}
     - REPO_USER=${WATCHTOWER_REPO_USER}
     - TZ=${TZ}
     - WATCHTOWER_CLEANUP=${WATCHTOWER_CLEANUP}
     - WATCHTOWER_INCLUDE_STOPPED=${WATCHTOWER_INCLUDE_STOPPED}
     - WATCHTOWER_MONITOR_ONLY=${WATCHTOWER_MONITOR_ONLY}
     - WATCHTOWER_NOTIFICATION_TEMPLATE=${WATCHTOWER_NOTIFICATION_TEMPLATE}
     - WATCHTOWER_NOTIFICATION_URL=${WATCHTOWER_NOTIFICATION_URL}
     - WATCHTOWER_NOTIFICATIONS_LEVEL=${WATCHTOWER_NOTIFICATIONS_LEVEL}
     - WATCHTOWER_NOTIFICATIONS=${WATCHTOWER_NOTIFICATIONS}
     - WATCHTOWER_SCHEDULE=${WATCHTOWER_SCHEDULE}
     - WATCHTOWER_TIMEOUT=${WATCHTOWER_TIMEOUT}
   logging:
     driver: json-file
     options:
       max-file: ${DOCKERLOGGING_MAXFILE}
       max-size: ${DOCKERLOGGING_MAXSIZE}
   restart: unless-stopped
   volumes:
     - /etc/localtime:/etc/localtime:ro
     - /var/run/docker.sock:/var/run/docker.sock
     - ${DOCKERSTORAGEDIR}:/storage
 ```

here the env file 
```
WATCHTOWER_CLEANUP=true
WATCHTOWER_ENABLED=true
WATCHTOWER_INCLUDE_STOPPED=false
WATCHTOWER_MONITOR_ONLY=false
WATCHTOWER_NETWORK_MODE=
WATCHTOWER_NOTIFICATIONS_LEVEL=info
WATCHTOWER_NOTIFICATIONS=shoutrrr
WATCHTOWER_NOTIFICATION_TEMPLATE={{range .}}{{.Message}}{{println}}{{end}}
WATCHTOWER_NOTIFICATION_URL=
WATCHTOWER_REPO_PASS=
WATCHTOWER_REPO_USER=
WATCHTOWER_SCHEDULE=0 0 4 * * *
WATCHTOWER_TIMEOUT=40s
```

```
  `.::///+:/-.        --///+//-:``    pi@raspberrypi
 `+oooooooooooo:   `+oooooooooooo:    --------------
  /oooo++//ooooo:  ooooo+//+ooooo.    OS: Raspbian GNU/Linux 10 (buster) armv7l
  `+ooooooo:-:oo-  +o+::/ooooooo:     Host: Raspberry Pi 4 Model B Rev 1.4
   `:oooooooo+``    `.oooooooo+-      Kernel: 5.10.17-v7l+
     `:++ooo/.        :+ooo+/.`       Uptime: 18 hours, 6 mins
        ...`  `.----.` ``..           Packages: 1895 (dpkg)
     .::::-``:::::::::.`-:::-`        Shell: bash 5.0.3
    -:::-`   .:::::::-`  `-:::-       Terminal: /dev/pts/0
   `::.  `.--.`  `` `.---.``.::`      CPU: BCM2711 (4) @ 1.500GHz
       .::::::::`  -::::::::` `       Memory: 1353MiB / 7874MiB
 .::` .:::::::::- `::::::::::``::.
-:::` ::::::::::.  ::::::::::.`:::-
::::  -::::::::.   `-::::::::  ::::
-::-   .-:::-.``....``.-::-.   -::-
 .. ``       .::::::::.     `..`..
   -:::-`   -::::::::::`  .:::::`
   :::::::` -::::::::::` :::::::.
   .:::::::  -::::::::. ::::::::
    `-:::::`   ..--.`   ::::::.
      `...`  `...--..`  `...`
            .::::::::::
             `.-::::-`

```



Pull request:
fix(notifier): don't panic on unconfigured notifier
When `notifications` is populated, but the corresponding options for configuring the notifications are not provided watchtower currently panics when trying to write out what notifications it uses.
This will instead simply print `none`, which is much more helpful.

Fixes #867 

Patch:
diff --git a/build.sh b/build.sh
index 363dc74..47d2b5c 100644
--- a/build.sh
+++ b/build.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
 
-VERSION=$(git describe)
+VERSION=$(git describe --tags)
 echo "Building $VERSION..."
-go build -o watchtower -ldflags "-X github.com/containrrr/watchtower/cmd.version=$VERSION"
\ No newline at end of file
+go build -o watchtower -ldflags "-X github.com/containrrr/watchtower/cmd.version=$VERSION"
diff --git a/dockerfiles/Dockerfile.dev-self-contained b/dockerfiles/Dockerfile.dev-self-contained
index 307ffbe..b22ef13 100644
--- a/dockerfiles/Dockerfile.dev-self-contained
+++ b/dockerfiles/Dockerfile.dev-self-contained
@@ -4,8 +4,8 @@
 
 FROM golang:alpine as builder
 
-# use version (for example "v0.3.3") or "master"
-ARG WATCHTOWER_VERSION=master
+# use version (for example "v0.3.3") or "main"
+ARG WATCHTOWER_VERSION=main
 
 RUN apk add --no-cache \
     alpine-sdk \
@@ -18,7 +18,7 @@ COPY . /watchtower
 RUN \
   cd /watchtower && \
   \
-  GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' . && \
+  GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -ldflags "-extldflags '-static' -X github.com/containrrr/watchtower/cmd.version=$(git describe --tags)" . && \
   GO111MODULE=on go test ./... -v
 
 
diff --git a/dockerfiles/Dockerfile.self-contained b/dockerfiles/Dockerfile.self-contained
index 64d5dc0..f24701f 100644
--- a/dockerfiles/Dockerfile.self-contained
+++ b/dockerfiles/Dockerfile.self-contained
@@ -4,8 +4,8 @@
 
 FROM golang:alpine as builder
 
-# use version (for example "v0.3.3") or "master"
-ARG WATCHTOWER_VERSION=master
+# use version (for example "v0.3.3") or "main"
+ARG WATCHTOWER_VERSION=main
 
 RUN apk add --no-cache \
     alpine-sdk \
@@ -18,7 +18,7 @@ RUN git clone --branch "${WATCHTOWER_VERSION}" https://github.com/containrrr/wat
 RUN \
   cd watchtower && \
   \
-  GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' . && \
+  GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -ldflags "-extldflags '-static' -X github.com/containrrr/watchtower/cmd.version=$(git describe --tags)" . && \
   GO111MODULE=on go test ./... -v
 
 
diff --git a/mkdocs.yml b/mkdocs.yml
index b40f794..67529aa 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,7 +1,7 @@
 site_name: Watchtower
 site_url: http://containrrr.github.io/watchtower/
 repo_url: https://github.com/containrrr/watchtower/
-edit_uri: edit/main/docs/index.md
+edit_uri: edit/main/docs/
 theme:
   name: 'material'
   palette:
diff --git a/pkg/notifications/notifier.go b/pkg/notifications/notifier.go
index b9e322e..ec313a5 100644
--- a/pkg/notifications/notifier.go
+++ b/pkg/notifications/notifier.go
@@ -55,6 +55,12 @@ func (n *Notifier) String() string {
 			sb.WriteString(", ")
 		}
 	}
+
+	if sb.Len() < 2 {
+		// No notification services are configured, return early as the separator strip is not applicable
+		return "none"
+	}
+
 	names := sb.String()
 
 	// remove the last separator


Test patch:
diff --git a/pkg/notifications/notifier_test.go b/pkg/notifications/notifier_test.go
index 5ef75a0..ecd228f 100644
--- a/pkg/notifications/notifier_test.go
+++ b/pkg/notifications/notifier_test.go
@@ -23,6 +23,22 @@ func TestActions(t *testing.T) {
 }
 
 var _ = Describe("notifications", func() {
+	Describe("the notifier", func() {
+		When("only empty notifier types are provided", func() {
+
+			command := cmd.NewRootCommand()
+			flags.RegisterNotificationFlags(command)
+
+			err := command.ParseFlags([]string{
+				"--notifications",
+				"shoutrrr",
+			})
+			Expect(err).NotTo(HaveOccurred())
+			notif := notifications.NewNotifier(command)
+
+			Expect(notif.String()).To(Equal("none"))
+		})
+	})
 	Describe("the slack notifier", func() {
 		builderFn := notifications.NewSlackNotifier