fix: add HealthCheckListResponse type to match API response structure
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 46s
CI Pipeline / Rust Unit Tests (push) Successful in 1m1s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Failing after 10s
CI Pipeline / Build .deb & Release (push) Has been skipped
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 46s
CI Pipeline / Rust Unit Tests (push) Successful in 1m1s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Failing after 10s
CI Pipeline / Build .deb & Release (push) Has been skipped
- Added HealthCheckListResponse type { checks: [...], total: number }
- Updated healthChecksApi.list() return type to HealthCheckListResponse
- Fixed HostDetailPage to use res.data?.checks instead of Array.isArray
- Added Target column to health checks table
- Added git pre-commit/pre-push hooks to prevent format CI failures
- Updated lessons.md
This commit is contained in:
@ -11,6 +11,7 @@ import type {
|
|||||||
HealthCheckWithResult,
|
HealthCheckWithResult,
|
||||||
CreateHealthCheckRequest,
|
CreateHealthCheckRequest,
|
||||||
UpdateHealthCheckRequest,
|
UpdateHealthCheckRequest,
|
||||||
|
HealthCheckListResponse,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
|
||||||
const BASE_URL = '/api/v1'
|
const BASE_URL = '/api/v1'
|
||||||
@ -273,7 +274,7 @@ export const settingsApi = {
|
|||||||
|
|
||||||
export const healthChecksApi = {
|
export const healthChecksApi = {
|
||||||
list: (hostId: string) =>
|
list: (hostId: string) =>
|
||||||
apiClient.get<HealthCheckWithResult[]>(`/hosts/${hostId}/health-checks`),
|
apiClient.get<HealthCheckListResponse>(`/hosts/${hostId}/health-checks`),
|
||||||
|
|
||||||
get: (hostId: string, checkId: string) =>
|
get: (hostId: string, checkId: string) =>
|
||||||
apiClient.get<HealthCheckWithResult>(`/hosts/${hostId}/health-checks/${checkId}`),
|
apiClient.get<HealthCheckWithResult>(`/hosts/${hostId}/health-checks/${checkId}`),
|
||||||
|
|||||||
@ -299,6 +299,11 @@ export interface HealthCheckWithResult extends HealthCheck {
|
|||||||
last_result?: HealthCheckResult
|
last_result?: HealthCheckResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HealthCheckListResponse {
|
||||||
|
checks: HealthCheckWithResult[]
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateHealthCheckRequest {
|
export interface CreateHealthCheckRequest {
|
||||||
name: string
|
name: string
|
||||||
check_type: HealthCheckType
|
check_type: HealthCheckType
|
||||||
|
|||||||
27
scripts/git-hooks/install.sh
Executable file
27
scripts/git-hooks/install.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Linux Patch Manager — Git Hooks Installer
|
||||||
|
# =============================================================================
|
||||||
|
# Installs pre-commit and pre-push hooks into .git/hooks/
|
||||||
|
# Run from repo root: ./scripts/git-hooks/install.sh
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
HOOKS_DIR="${REPO_ROOT}/.git/hooks"
|
||||||
|
SOURCE_DIR="${REPO_ROOT}/scripts/git-hooks"
|
||||||
|
|
||||||
|
echo "Installing git hooks from ${SOURCE_DIR} ..."
|
||||||
|
|
||||||
|
for hook in pre-commit pre-push; do
|
||||||
|
if [[ -f "${SOURCE_DIR}/${hook}" ]]; then
|
||||||
|
cp "${SOURCE_DIR}/${hook}" "${HOOKS_DIR}/${hook}"
|
||||||
|
chmod +x "${HOOKS_DIR}/${hook}"
|
||||||
|
echo " ✓ Installed ${hook}"
|
||||||
|
else
|
||||||
|
echo " ⚠ Skipped ${hook} (not found)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Done. Hooks will run automatically on commit and push."
|
||||||
33
scripts/git-hooks/pre-commit
Executable file
33
scripts/git-hooks/pre-commit
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Linux Patch Manager — Pre-Commit Hook
|
||||||
|
# =============================================================================
|
||||||
|
# Auto-formats Rust code and runs frontend type check before each commit.
|
||||||
|
# Prevents CI format-check failures by ensuring code is always formatted.
|
||||||
|
# Install: ./scripts/git-hooks/install.sh
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
# ── Rust auto-format ──────────────────────────────────────────────────────────
|
||||||
|
if [[ -f "${REPO_ROOT}/Cargo.toml" ]]; then
|
||||||
|
echo "[pre-commit] Running cargo fmt --all ..."
|
||||||
|
cargo fmt --all --manifest-path "${REPO_ROOT}/Cargo.toml" 2>/dev/null
|
||||||
|
|
||||||
|
# Re-stage any files that cargo fmt reformatted (including previously unstaged)
|
||||||
|
STAGED_RS=$(git diff --name-only --diff-filter=ACM -- '*.rs')
|
||||||
|
if [[ -n "${STAGED_RS}" ]]; then
|
||||||
|
git add ${STAGED_RS}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Frontend type check ─────────────────────────────────────────────────────
|
||||||
|
if [[ -f "${REPO_ROOT}/frontend/package.json" ]]; then
|
||||||
|
echo "[pre-commit] Running TypeScript type check ..."
|
||||||
|
cd "${REPO_ROOT}/frontend"
|
||||||
|
npx tsc --noEmit 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[pre-commit] All checks passed ✓"
|
||||||
37
scripts/git-hooks/pre-push
Executable file
37
scripts/git-hooks/pre-push
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Linux Patch Manager — Pre-Push Hook
|
||||||
|
# =============================================================================
|
||||||
|
# Safety net: verifies cargo fmt and frontend build pass before pushing.
|
||||||
|
# Install: ./scripts/git-hooks/install.sh
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
FAILED=0
|
||||||
|
|
||||||
|
# ── Rust format check ────────────────────────────────────────────────────────
|
||||||
|
if [[ -f "${REPO_ROOT}/Cargo.toml" ]]; then
|
||||||
|
echo "[pre-push] Checking Rust formatting ..."
|
||||||
|
if ! cargo fmt --all --manifest-path "${REPO_ROOT}/Cargo.toml" --check 2>/dev/null; then
|
||||||
|
echo "[pre-push] ❌ Rust formatting check FAILED. Run: cargo fmt --all"
|
||||||
|
FAILED=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Frontend type check ─────────────────────────────────────────────────────
|
||||||
|
if [[ -f "${REPO_ROOT}/frontend/package.json" ]]; then
|
||||||
|
echo "[pre-push] Checking TypeScript types ..."
|
||||||
|
if ! (cd "${REPO_ROOT}/frontend" && npx tsc --noEmit 2>/dev/null); then
|
||||||
|
echo "[pre-push] ❌ TypeScript type check FAILED."
|
||||||
|
FAILED=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${FAILED} -ne 0 ]]; then
|
||||||
|
echo "[pre-push] Push rejected — fix errors above before pushing."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[pre-push] All checks passed ✓"
|
||||||
@ -65,3 +65,18 @@ The Docker container intercepted some jobs and ran them in its Alpine environmen
|
|||||||
**Fix:** Stopped Docker container runner. Switched to runs-on: ubuntu-latest with docker://ubuntu:24.04 containers.
|
**Fix:** Stopped Docker container runner. Switched to runs-on: ubuntu-latest with docker://ubuntu:24.04 containers.
|
||||||
|
|
||||||
**Lesson:** Check for multiple runners with same name. Stop after 2 attempts and diagnose root cause.
|
**Lesson:** Check for multiple runners with same name. Stop after 2 attempts and diagnose root cause.
|
||||||
|
|
||||||
|
## 2026-05-05: Always Use Git → Gitea → Runner CI/CD Pipeline for Deployment
|
||||||
|
**Pattern:** When deploying code changes to any environment, always commit and push to Gitea and let the CI/CD pipeline handle building and deployment.
|
||||||
|
**Why:** Manually copying built files (scp, etc.) bypasses quality gates (format, clippy, test, lint) and is not reproducible. The CI pipeline ensures every change passes all checks before reaching any environment.
|
||||||
|
**Action:** Never manually copy files to servers. Always: commit → push to Gitea → let CI/CD run → deploy through proper pipeline.
|
||||||
|
|
||||||
|
## 2026-05-05: Verify API Response Structure Matches Frontend Expectations
|
||||||
|
**Pattern:** When frontend data doesn't appear, check the API response structure before assuming the UI code is wrong.
|
||||||
|
**Why:** Health checks list was always empty because backend returns `{ checks: [...], total: N }` but frontend used `Array.isArray(res.data) ? res.data : []` which returned `[]` for an object. Maintenance windows worked because they correctly used `res.data?.windows ?? []`.
|
||||||
|
**Action:** When adding new API endpoints, verify the response wrapper structure matches what the frontend expects. Check existing working patterns (like maintenance windows) for the correct data extraction approach.
|
||||||
|
|
||||||
|
## 2026-05-05: Run cargo fmt Before Pushing to Avoid CI Failures
|
||||||
|
**Pattern:** Always run `cargo fmt --all` locally before pushing Rust code changes.
|
||||||
|
**Why:** The CI pipeline has a Rust Format Check gate that will fail if code isn't formatted. This wastes CI runner time and delays deployment.
|
||||||
|
**Action:** Run `cargo fmt --all` as part of local pre-push checklist, alongside `npm run build` for frontend changes.
|
||||||
|
|||||||
Reference in New Issue
Block a user