Skip to content

Commit f28e356

Browse files
authored
feat: added manual upgrade from ui (#17)
* feat: add server health check and upgrade endpoints - Implemented `/server/health` endpoint to check server health status. - Added `/server/upgrade` endpoint to trigger manual server upgrades. - Updated Swagger documentation to reflect new endpoints and responses. - Introduced new types for health check and upgrade responses. - Refactored server info handling to use Zustand for state management. - Enhanced the update banner with upgrade functionality and confirmation dialog. - Improved configuration management by consolidating and validating settings. - Removed deprecated error and success response types from the web package. * refactor: enhance toast notifications for server upgrade process * feat: add build date to Docker image and update docker-compose configuration * refactor: update Docker image build platforms to remove unsupported architectures * feat: truncate commit hash display in server info to first 8 characters * feat: add curl installation to Dockerfile for enhanced functionality * feat: update version command to display full build version details * feat: update version command to use 'version' flag for consistency * refactor: comment out unsupported Docker image build platforms * feat: enhance upgrader initialization and add is_available_manual field to update structures
1 parent c7bfc79 commit f28e356

37 files changed

Lines changed: 1033 additions & 286 deletions

.github/workflows/release.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ jobs:
8080
- name: Set up Docker Buildx
8181
uses: docker/setup-buildx-action@v3
8282

83+
- name: Get current date
84+
id: date
85+
run: echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
86+
8387
- name: Login to DockerHub
8488
uses: docker/login-action@v3
8589
with:
@@ -89,6 +93,7 @@ jobs:
8993
- name: Build and push Docker image
9094
uses: docker/build-push-action@v6
9195
with:
96+
# platforms: linux/amd64,linux/arm64
9297
context: .
9398
push: true
9499
tags: |
@@ -97,3 +102,4 @@ jobs:
97102
build-args: |
98103
VERSION=${{ github.ref_name }}
99104
COMMIT_HASH=${{ github.sha }}
105+
BUILD_DATE=${{ steps.date.outputs.date }}

Dockerfile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ RUN pnpm run build
1919
FROM golang:1.24-alpine AS backend-builder
2020

2121
# Define build arguments for version, commit, and date.
22-
ARG VERSION=$(git describe --tags --abbrev=0 || echo "0.0.0")
23-
ARG COMMIT_HASH=$(git rev-parse --short HEAD || echo "none")
24-
ARG BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
22+
ARG VERSION="unknown"
23+
ARG COMMIT_HASH="unknown"
24+
ARG BUILD_DATE="unknown"
2525

2626
# Install dependencies
2727
RUN apk add --no-cache ca-certificates
@@ -40,13 +40,13 @@ COPY . .
4040
COPY --from=frontend-builder /app/frontend/dist ./frontend/dist
4141

4242
# Build the application with embedded frontend
43-
RUN CGO_ENABLED=0 go build -a -installsuffix -ldflags="-w -s -X main.version=${VERSION} -X main.commitHash=${COMMIT_HASH} -X main.buildDate=${BUILD_DATE}" -o bin/sentinel ./cmd/sentinel
43+
RUN go build -trimpath -ldflags="-w -s -X 'main.version=${VERSION}' -X 'main.commitHash=${COMMIT_HASH}' -X 'main.buildDate=${BUILD_DATE}'" -o bin/sentinel ./cmd/sentinel
4444

4545
# Final stage
4646
FROM alpine:latest
4747

4848
# Install ca-certificates for HTTPS requests
49-
RUN apk --no-cache add ca-certificates tzdata
49+
RUN apk --no-cache add ca-certificates tzdata curl
5050

5151
WORKDIR /root/
5252

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ docker-stop: ## Stop Docker container
9292
docker stop sentinel || true
9393
docker rm sentinel || true
9494

95+
deocker-dev:
96+
docker compose -f docker-compose.local.yml up -d
97+
9598
# Docker Compose
9699
up: ## Start with docker-compose
97100
docker-compose up -d

cmd/sentinel/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func main() {
4646
app := &cli.Command{
4747
Name: appName,
4848
Usage: "A CLI application for " + appName,
49-
Version: version,
49+
Version: getBuildVersion(),
5050
Suggest: true,
5151
Commands: []*cli.Command{
5252
startCMD(),

cmd/sentinel/start.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/sxwebdev/sentinel/internal/receiver"
1313
"github.com/sxwebdev/sentinel/internal/scheduler"
1414
"github.com/sxwebdev/sentinel/internal/storage"
15+
"github.com/sxwebdev/sentinel/internal/upgrader"
1516
"github.com/sxwebdev/sentinel/internal/web"
1617
"github.com/tkcrm/mx/launcher"
1718
"github.com/tkcrm/mx/logger"
@@ -80,6 +81,12 @@ func startCMD() *cli.Command {
8081
// Init receiver
8182
rc := receiver.New()
8283

84+
// Initialize upgrader if configured
85+
upgr, err := upgrader.New(l, conf.Upgrader)
86+
if err != nil {
87+
return fmt.Errorf("failed to initialize upgrader: %w", err)
88+
}
89+
8390
// Create monitor service
8491
monitorService := monitor.NewMonitorService(store, conf, notif, rc)
8592

@@ -94,7 +101,7 @@ func startCMD() *cli.Command {
94101
SqliteVersion: sqliteVersion,
95102
OS: runtime.GOOS,
96103
Arch: runtime.GOARCH,
97-
}, monitorService, store, rc)
104+
}, monitorService, store, rc, upgr)
98105
if err != nil {
99106
return fmt.Errorf("failed to initialize web server: %w", err)
100107
}

cmd/sentinel/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func versionCMD() *cli.Command {
1212
Name: "version",
1313
Usage: "print current version",
1414
Action: func(_ context.Context, _ *cli.Command) error {
15-
fmt.Printf("%s version %s\n", appName, getBuildVersion())
15+
fmt.Println(version)
1616
return nil
1717
},
1818
}

cmd/testapi/main.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/sxwebdev/sentinel/internal/notifier"
2121
"github.com/sxwebdev/sentinel/internal/receiver"
2222
"github.com/sxwebdev/sentinel/internal/storage"
23+
"github.com/sxwebdev/sentinel/internal/upgrader"
2324
"github.com/sxwebdev/sentinel/internal/web"
2425
"github.com/sxwebdev/sentinel/pkg/dbutils"
2526
"github.com/tkcrm/mx/logger"
@@ -238,11 +239,17 @@ func setupTestSuite() (*TestSuite, error) {
238239
return nil, fmt.Errorf("failed to start receiver: %w", err)
239240
}
240241

242+
// Initialize upgrader if configured
243+
upgr, err := upgrader.New(l, cfg.Upgrader)
244+
if err != nil {
245+
return nil, fmt.Errorf("failed to initialize upgrader: %w", err)
246+
}
247+
241248
// Create monitor service
242249
monitorService := monitor.NewMonitorService(stor, cfg, notif, rc)
243250

244251
// Create web server
245-
webServer, err := web.NewServer(l, cfg, web.ServerInfo{}, monitorService, stor, rc)
252+
webServer, err := web.NewServer(l, cfg, web.ServerInfo{}, monitorService, stor, rc, upgr)
246253
if err != nil {
247254
return nil, fmt.Errorf("failed to create web server: %w", err)
248255
}

docker-compose.local.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
version: "3.8"
2-
31
services:
42
sentinel:
5-
build: .
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
args:
7+
VERSION: local-dev
8+
COMMIT_HASH: local
9+
BUILD_DATE: local
610
ports:
711
- "8080:8080"
812
volumes:

docker-compose.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: "3.8"
2-
31
services:
42
sentinel:
53
image: sxwebdev/sentinel:latest

docs/docsv1/docs.go

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,36 @@ const docTemplate = `{
108108
}
109109
}
110110
},
111-
"/info": {
111+
"/server/health": {
112+
"get": {
113+
"description": "Checks the health of the server",
114+
"consumes": [
115+
"application/json"
116+
],
117+
"produces": [
118+
"application/json"
119+
],
120+
"tags": [
121+
"server"
122+
],
123+
"summary": "Health check",
124+
"responses": {
125+
"200": {
126+
"description": "Health check successful",
127+
"schema": {
128+
"$ref": "#/definitions/web.healthCheckResponse"
129+
}
130+
},
131+
"500": {
132+
"description": "Internal server error",
133+
"schema": {
134+
"$ref": "#/definitions/web.ErrorResponse"
135+
}
136+
}
137+
}
138+
}
139+
},
140+
"/server/info": {
112141
"get": {
113142
"description": "Returns basic information about the server",
114143
"consumes": [
@@ -118,7 +147,7 @@ const docTemplate = `{
118147
"application/json"
119148
],
120149
"tags": [
121-
"info"
150+
"server"
122151
],
123152
"summary": "Get server info",
124153
"responses": {
@@ -137,6 +166,35 @@ const docTemplate = `{
137166
}
138167
}
139168
},
169+
"/server/upgrade": {
170+
"get": {
171+
"description": "Triggers a manual upgrade of the server",
172+
"consumes": [
173+
"application/json"
174+
],
175+
"produces": [
176+
"application/json"
177+
],
178+
"tags": [
179+
"server"
180+
],
181+
"summary": "Manual upgrade",
182+
"responses": {
183+
"200": {
184+
"description": "Upgrade initiated successfully",
185+
"schema": {
186+
"$ref": "#/definitions/web.SuccessResponse"
187+
}
188+
},
189+
"500": {
190+
"description": "Internal server error",
191+
"schema": {
192+
"$ref": "#/definitions/web.ErrorResponse"
193+
}
194+
}
195+
}
196+
}
197+
},
140198
"/services": {
141199
"get": {
142200
"description": "Returns a list of all services with their current states",
@@ -983,6 +1041,9 @@ const docTemplate = `{
9831041
"description": {
9841042
"type": "string"
9851043
},
1044+
"is_available_manual": {
1045+
"type": "boolean"
1046+
},
9861047
"tag_name": {
9871048
"type": "string"
9881049
},
@@ -1237,6 +1298,15 @@ const docTemplate = `{
12371298
"example": "Operation completed successfully"
12381299
}
12391300
}
1301+
},
1302+
"web.healthCheckResponse": {
1303+
"type": "object",
1304+
"properties": {
1305+
"status": {
1306+
"type": "string",
1307+
"example": "healthy"
1308+
}
1309+
}
12401310
}
12411311
},
12421312
"securityDefinitions": {

0 commit comments

Comments
 (0)