Skip to content

Commit

Permalink
add ntfy support
Browse files Browse the repository at this point in the history
  • Loading branch information
cdzombak committed Oct 25, 2023
1 parent fd00bd4 commit 3b760f2
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 11 deletions.
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

`runner` runs a program, capturing its output (from both standard output and standard error) and printing it to standard output only if the program fails.

The output can also be printed if the program produces, or does not produce, a specific string. As of Runner 2.0.0, output can always be printed regardless of program exit status, with the `-always-print` option.
The output can also be printed if the program produces, or does not produce, a specific string (see `-print-if-match` and `-print-if-not-match`). As of Runner 2.0.0, output can always be printed regardless of program exit status, with the `-always-print` option.

Output is optionally written to a log directory regardless of program exit status.
If the program failed, or its output would otherwise be printed, `runner` can also:

`runner` can also email the program's output if provided with an SMTP server and credentials.
- email the program's output, if provided with an SMTP server and credentials
- send a notification via [ntfy](https://ntfy.sh).

Output is optionally written to a log directory, regardless of program exit status.

If `runner` is run as `root` or with `CAP_SETUID` and `CAP_SETGID`, the target program can be run as a different user.

Expand All @@ -20,7 +23,7 @@ The core `runner` logic (capturing and discarding program output) is useful when

### Containers

`runner` 2.0.0 is useful in various containerization applications, even as a container entrypoint, since it can run a target program in the container, retry it if need be, and capture and email its output.
`runner` 2.0.0 is useful in various containerization applications, even as a container entrypoint, since it can run a target program in the container, retry it if need be, and capture and email its output or send it to a ntfy server. Email and ntfy outputs can be configured by the image's end user via environment variables, requiring no build-time customization.

It can even run the target program as a non-root user, and if `runner` is not the container's entrypoint, you can set environment variables like the following to redirect output to the root process's stdout/stderr:

Expand Down Expand Up @@ -96,7 +99,7 @@ If you plan to use the `RUNNER_OUTFD_PID` and `RUNNER_OUTFD_STD[OUT|ERR]` variab
- `-version`: Print version and exit.
- `-work-dir string`: Set the working directory for the program.

- `RUNNER_CENSOR_ENV` (environment variable only): Colon-separated list of environment variables whose values will be censored in output.
- `RUNNER_CENSOR_ENV` (environment variable only): Colon-separated list of environment variables whose values will be censored in output. `RUNNER_SMTP_PASS` and `RUNNER_NTFY_ACCESS_TOKEN` are always censored.
- `RUNNER_HIDE_ENV` (environment variable only): Colon-separated list of environment variables which will be entirely omitted from output.

#### Run as another user
Expand All @@ -122,6 +125,21 @@ If you plan to use the `RUNNER_OUTFD_PID` and `RUNNER_OUTFD_STD[OUT|ERR]` variab
- `-smtp-user string`: Username for SMTP authentication.
- Can also be set by the `RUNNER_SMTP_USER` environment variable; this flag overrides the environment variable.

#### Ntfy Options

- `-ntfy-access-token string`: If set, use this access token for ntfy.
- Can also be set by the RUNNER_NTFY_ACCESS_TOKEN environment variable; this flag overrides the environment variable.
- `-ntfy-email string`: If set, tell ntfy to send an email to this address.
- Can also be set by the RUNNER_NTFY_EMAIL environment variable; this flag overrides the environment variable.
- `-ntfy-priority int`: Priority for the notification sent to ntfy. Must be between 1-5, inclusive.
- Can also be set by the RUNNER_NTFY_PRIORITY environment variable; this flag overrides the environment variable. (default 3)
- `-ntfy-server string`: Send a notification to the given ntfy server if the program fails or its output would otherwise be printed per -healthy-exit/-print-if-[not]-match/-always-print.
- Can also be set by the RUNNER_NTFY_SERVER environment variable; this flag overrides the environment variable.
- `-ntfy-tags string`: Comma-separated list of ntfy tags to send.
- Can also be set by the RUNNER_NTFY_TAGS environment variable; this flag overrides the environment variable.
- `-ntfy-topic string`: The ntfy topic to send to.
- Can also be set by the RUNNER_NTFY_TOPIC environment variable; this flag overrides the environment variable.

### Sample Output

```text
Expand Down
7 changes: 5 additions & 2 deletions envprivacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ func hiddenEnvVars() []string {
}

func censoredEnvVars() []string {
return strings.Split(os.Getenv(CensorEnvVarsEnvVar), ":")
retv := strings.Split(os.Getenv(CensorEnvVarsEnvVar), ":")
retv = append(retv, SMTPPassEnvVar)
retv = append(retv, NtfyAccessTokenEnvVar)
return retv
}

func shouldHideEnvVar(varName string) bool {
return stringSliceContains(hiddenEnvVars(), varName)
}

func censoredEnvVarValue(varName, value string) string {
if !stringSliceContains(censoredEnvVars(), varName) && varName != SMTPPassEnvVar {
if !stringSliceContains(censoredEnvVars(), varName) {
return value
}
if len(value) < minLenForCensorHint {
Expand Down
14 changes: 14 additions & 0 deletions flaghelp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import "flag"

// WasFlagGiven returns true if the flag was given on the command line.
func WasFlagGiven(flagName string) bool {
retv := false
flag.Visit(func(f *flag.Flag) {
if f.Name == flagName {
retv = true
}
})
return retv
}
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ module runner

go 1.15

require github.com/oraoto/go-pidfd v0.1.1 // indirect
require (
github.com/AnthonyHewins/gotfy v0.0.6
github.com/oraoto/go-pidfd v0.1.1
)

replace github.com/AnthonyHewins/gotfy => github.com/cdzombak/gotfy v0.0.0-20231025000242-bc5cb9291587
54 changes: 54 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,56 @@
github.com/cdzombak/gotfy v0.0.0-20231024183704-5b0245ab1816 h1:UKYPL1SrvMLdz+GtEgDhi9Viodorx4lfzycAWpgC8X4=
github.com/cdzombak/gotfy v0.0.0-20231024183704-5b0245ab1816/go.mod h1:GuKBi08/7tvMfw3504yTS6bL8WciANd6czvey2k9tAs=
github.com/cdzombak/gotfy v0.0.0-20231025000242-bc5cb9291587 h1:ezh7FtsHmaezVLVarhC+Pz6K0ddWqYh1+FsP2TnK488=
github.com/cdzombak/gotfy v0.0.0-20231025000242-bc5cb9291587/go.mod h1:GuKBi08/7tvMfw3504yTS6bL8WciANd6czvey2k9tAs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/oraoto/go-pidfd v0.1.1 h1:57gTETdUGYpFwRKoKph8ffgeps89DF2qlfxBFdfkHiA=
github.com/oraoto/go-pidfd v0.1.1/go.mod h1:gPWelSU60MvzRX+ToMlKj9lZRkeqybg6qy8cy4+rZWE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
108 changes: 105 additions & 3 deletions runner.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"context"
"errors"
"flag"
"fmt"
"log"
"net/smtp"
"net/url"
"os"
"os/exec"
"os/user"
Expand All @@ -15,6 +17,8 @@ import (
"strings"
"syscall"
"time"

"github.com/AnthonyHewins/gotfy"
)

var version = "<dev>"
Expand All @@ -29,6 +33,13 @@ const (
SMTPPortEnvVar = "RUNNER_SMTP_PORT"
MailTabCharEnvVar = "RUNNER_MAIL_TAB_CHAR"

NtfyServerEnvVar = "RUNNER_NTFY_SERVER"
NtfyTopicEnvVar = "RUNNER_NTFY_TOPIC"
NtfyTagsEnvVar = "RUNNER_NTFY_TAGS"
NtfyPriorityEnvVar = "RUNNER_NTFY_PRIORITY"
NtfyEmailEnvVar = "RUNNER_NTFY_EMAIL"
NtfyAccessTokenEnvVar = "RUNNER_NTFY_ACCESS_TOKEN"

OutFdPidEnvVar = "RUNNER_OUTFD_PID"
OutFdStdoutEnvVar = "RUNNER_OUTFD_STDOUT"
OutFdStderrEnvVar = "RUNNER_OUTFD_STDERR"
Expand All @@ -39,6 +50,8 @@ const (
CensorEnvVarsEnvVar = "RUNNER_CENSOR_ENV"
)

const ntfyTimeout = time.Second * 10

func usage() {
_, _ = fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] -- /path/to/program --program-args\n", filepath.Base(os.Args[0]))
_, _ = fmt.Fprintf(os.Stderr, "Run the given program, only printing its output if the program exits with an error, "+
Expand All @@ -52,7 +65,7 @@ func usage() {
flag.PrintDefaults()
_, _ = fmt.Fprintf(os.Stderr, "\nEnvironment variable-only options:\n")
_, _ = fmt.Fprintf(os.Stderr, " %s\n \tColon-separated list of environment variables whose values will be censored in output."+
"\n \tRUNNER_SMTP_PASS is always censored.\n", CensorEnvVarsEnvVar)
"\n \tRUNNER_SMTP_PASS and RUNNER_NTFY_ACCESS_TOKEN are always censored.\n", CensorEnvVarsEnvVar)
_, _ = fmt.Fprintf(os.Stderr, " %s\n \tColon-separated list of environment variables which will be entirely omitted from output.\n", HideEnvVarsEnvVar)
_, _ = fmt.Fprintf(os.Stderr, "\nVersion:\n runner %s\n", version)
_, _ = fmt.Fprintf(os.Stderr, "\nGitHub:\n https://github.com/cdzombak/runner\n")
Expand Down Expand Up @@ -105,6 +118,18 @@ func main() {
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable. (default: 25)", SMTPPortEnvVar))
mailTabCharReplacement := flag.String("mail-tab-char", "", "Replace tab characters in emailed output by this string. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", MailTabCharEnvVar))
ntfyServer := flag.String("ntfy-server", "", "Send a notification to the given ntfy server if the program fails or its output would otherwise be printed per -healthy-exit/-print-if-[not]-match/-always-print. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyServerEnvVar))
ntfyTopic := flag.String("ntfy-topic", "", "The ntfy topic to send to. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyTopicEnvVar))
ntfyTags := flag.String("ntfy-tags", "", "Comma-separated list of ntfy tags to send. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyTagsEnvVar))
ntfyPriority := flag.Int("ntfy-priority", 3, "Priority for the notification sent to ntfy. Must be between 1-5, inclusive. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyPriorityEnvVar))
ntfyEmail := flag.String("ntfy-email", "", "If set, tell ntfy to send an email to this address. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyEmailEnvVar))
ntfyAccessToken := flag.String("ntfy-access-token", "", "If set, use this access token for ntfy. "+
fmt.Sprintf("Can also be set by the %s environment variable; this flag overrides the environment variable.", NtfyAccessTokenEnvVar))
printVersion := flag.Bool("version", false, "Print version and exit.")
flag.Usage = usage
flag.Parse()
Expand Down Expand Up @@ -220,6 +245,51 @@ func main() {
*mailTabCharReplacement = os.Getenv(MailTabCharEnvVar)
}

ntfyOutput := false
if *ntfyServer == "" {
*ntfyServer = os.Getenv(NtfyServerEnvVar)
}
if *ntfyTopic == "" {
*ntfyTopic = os.Getenv(NtfyTopicEnvVar)
}
if *ntfyTags == "" {
*ntfyTags = os.Getenv(NtfyTagsEnvVar)
}
if *ntfyEmail == "" {
*ntfyEmail = os.Getenv(NtfyEmailEnvVar)
}
if *ntfyAccessToken == "" {
*ntfyAccessToken = os.Getenv(NtfyAccessTokenEnvVar)
}
if os.Getenv(NtfyPriorityEnvVar) != "" && !WasFlagGiven("ntfy-priority") {
ntfyPriorityStr := os.Getenv(NtfyPriorityEnvVar)
*ntfyPriority, err = strconv.Atoi(ntfyPriorityStr)
if err != nil {
log.Fatalf("Failed to parse the given %s ('%s') as integer: %s", NtfyPriorityEnvVar, ntfyPriorityStr, err)
}
}
if *ntfyPriority < 1 || *ntfyPriority > 5 {
log.Fatalf("Invalid ntfy priority %d given; must be between 1-5, inclusive.", *ntfyPriority)
}
var ntfyServerURL *url.URL
if *ntfyServer != "" {
if !strings.HasPrefix(strings.ToLower(*ntfyServer), "http") {
*ntfyServer = "https://" + *ntfyServer
}

ntfyServerURL, err = url.Parse(*ntfyServer)
if err != nil {
log.Fatalf("Failed to parse the given ntfy server URL ('%s'): %s", *ntfyServer, err)
}

if *ntfyTopic != "" {
ntfyOutput = true
} else {
log.Fatalf("If using -ntfy-server (or the %s env var), you must also specify -ntfy-topic (%s).",
NtfyServerEnvVar, NtfyTopicEnvVar)
}
}

triesRemaining := 1 + *retries
programOutput := ""
var startTime, endTime time.Time
Expand Down Expand Up @@ -357,6 +427,8 @@ func main() {
if shouldPrint {
fmt.Printf(output)

summaryStr := fmt.Sprintf("[%s] %s running %s", hostname, statusStr, *jobName)

if mailOutput {
body := strings.ReplaceAll(output, "\n", "\r\n")
if *mailTabCharReplacement != "" {
Expand All @@ -370,7 +442,7 @@ func main() {
"X-Mailer: %s\r\n\r\n"+
"%s\r\n",
*mailFrom, *mailTo,
fmt.Sprintf("[%s] %s running %s", hostname, statusStr, *jobName),
summaryStr,
"runner "+version,
body,
))
Expand All @@ -379,7 +451,37 @@ func main() {
err = smtp.SendMail(smtpAddr, auth, *mailFrom, []string{*mailTo}, msg)

if err != nil {
warningLogs = append(warningLogs, fmt.Sprintf("Failed to send email to %s: %s", *mailTo, err))
warning := fmt.Sprintf("Failed to send email to %s: %s", *mailTo, err)
log.Println(warning)
output = output + fmt.Sprintf("\n[runner output warning] %s\n", warning)
}
}

if ntfyOutput {
ntfyPublisher, err := gotfy.NewPublisher(nil, ntfyServerURL, nil)
if err != nil {
warning := fmt.Sprintf("Failed to publish to ntfy: %s", err)
log.Println(warning)
output = output + fmt.Sprintf("\n[runner output warning] %s\n", warning)
} else {
if *ntfyAccessToken != "" {
ntfyPublisher.Headers.Set("authorization", fmt.Sprintf("Bearer %s", *ntfyAccessToken))
}
ctx, cancel := context.WithTimeout(context.Background(), ntfyTimeout)
defer cancel()
_, err = ntfyPublisher.SendMessage(ctx, &gotfy.Message{
Topic: *ntfyTopic,
Tags: strings.Split(*ntfyTags, ","),
Priority: gotfy.Priority(*ntfyPriority),
Email: *ntfyEmail,
Title: summaryStr,
Message: output,
})
if err != nil {
warning := fmt.Sprintf("Failed to publish to ntfy: %s", err)
log.Println(warning)
output = output + fmt.Sprintf("\n[runner output warning] %s\n", warning)
}
}
}
}
Expand Down

0 comments on commit 3b760f2

Please sign in to comment.