From 6b7e4df4911ab4529df34cc7e09de023991bda62 Mon Sep 17 00:00:00 2001 From: GAURAV KARMAKAR Date: Sun, 25 Jan 2026 01:24:34 +0530 Subject: [PATCH 1/2] feat: make health check fail when task binary is missing --- backend/controllers/healthcheck.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/controllers/healthcheck.go b/backend/controllers/healthcheck.go index 5d555496..a2d1da82 100644 --- a/backend/controllers/healthcheck.go +++ b/backend/controllers/healthcheck.go @@ -3,6 +3,7 @@ package controllers import ( "encoding/json" "net/http" + "os/exec" ) func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { @@ -11,10 +12,20 @@ func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { return } + status := "healthy" + statusCode := http.StatusOK + + // Check if taskwarrior is reachable + _, err := exec.LookPath("task") + if err != nil { + status = "unhealthy: taskwarrior binary not found" + statusCode = http.StatusServiceUnavailable + } + w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) + w.WriteHeader(statusCode) json.NewEncoder(w).Encode(map[string]string{ - "status": "healthy", + "status": status, "service": "ccsync-backend", }) } From 9d6f25e6da5b54dad2db65c8709d26a7e9a450cd Mon Sep 17 00:00:00 2001 From: GAURAV KARMAKAR Date: Mon, 2 Feb 2026 23:55:55 +0530 Subject: [PATCH 2/2] updating the PR applying the check for the version --- backend/controllers/healthcheck.go | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/backend/controllers/healthcheck.go b/backend/controllers/healthcheck.go index a2d1da82..b147d064 100644 --- a/backend/controllers/healthcheck.go +++ b/backend/controllers/healthcheck.go @@ -4,22 +4,42 @@ import ( "encoding/json" "net/http" "os/exec" + "regexp" + "strconv" ) func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { + // if it get any other request other than get then it will show error if r.Method != http.MethodGet { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } - + // Default state is healthy status := "healthy" statusCode := http.StatusOK - // Check if taskwarrior is reachable - _, err := exec.LookPath("task") + // checks the taskwarrior version and if the command fails will give 503 (dependency missing) + cmd := exec.Command("task", "--version") + output, err := cmd.Output() if err != nil { - status = "unhealthy: taskwarrior binary not found" + status = "unhealthy: taskwarrior not found or failed to execute" statusCode = http.StatusServiceUnavailable + } else { + re := regexp.MustCompile(`(\d+)\.(\d+)`) + matches := re.FindStringSubmatch(string(output)) + + if len(matches) < 3 { + status = "unhealthy: unable to determine taskwarrior version" + statusCode = http.StatusServiceUnavailable + } else { + // check the taskwarrior version (major version should be >= 3 ) + major, _ := strconv.Atoi(matches[1]) + + if major < 3 { + status = "unhealthy: unsupported taskwarrior version (>= 3.0 required)" + statusCode = http.StatusServiceUnavailable + } + } } w.Header().Set("Content-Type", "application/json")