fix: restore production OpenClaw runtime health
This commit is contained in:
@@ -61,7 +61,7 @@ JWT_ISSUER=nexus
|
|||||||
JWT_AUDIENCE=nexus-web
|
JWT_AUDIENCE=nexus-web
|
||||||
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
||||||
BOOTSTRAP_OWNER_PASSWORD=${ENV_BOOTSTRAP_OWNER_PASSWORD:-}
|
BOOTSTRAP_OWNER_PASSWORD=${ENV_BOOTSTRAP_OWNER_PASSWORD:-}
|
||||||
OPENCLAW_BASE_URL=http://host.docker.internal:18789
|
OPENCLAW_BASE_URL=http://openclaw-gateway:18789
|
||||||
OPENCLAW_REQUIRED_VERSION=2026.7.1
|
OPENCLAW_REQUIRED_VERSION=2026.7.1
|
||||||
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN:-}
|
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN:-}
|
||||||
OPENCLAW_GATEWAY_PASSWORD=
|
OPENCLAW_GATEWAY_PASSWORD=
|
||||||
@@ -141,11 +141,17 @@ for container in nexus-api-1 nexus-web-1; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "Checking live health"
|
echo "Checking live health"
|
||||||
|
health_is_healthy() {
|
||||||
|
health_body="$(curl -fsS --max-time 10 "$BASE_URL/health")" || return 1
|
||||||
|
printf '%s' "$health_body" |
|
||||||
|
grep -Eq '^[[:space:]]*\{[[:space:]]*"status"[[:space:]]*:[[:space:]]*"Healthy"'
|
||||||
|
}
|
||||||
|
|
||||||
retry=0
|
retry=0
|
||||||
while [ "$retry" -lt 6 ]; do
|
while [ "$retry" -lt 6 ]; do
|
||||||
retry=$((retry + 1))
|
retry=$((retry + 1))
|
||||||
if curl -fsS --max-time 10 "$BASE_URL/health" >/dev/null; then
|
if health_is_healthy; then
|
||||||
echo "Health check passed"
|
echo "Health check passed with Healthy runtime and database state"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [ "$retry" -eq 6 ]; then
|
if [ "$retry" -eq 6 ]; then
|
||||||
@@ -170,6 +176,16 @@ check() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_health() {
|
||||||
|
if health_is_healthy; then
|
||||||
|
printf '%-28s HTTP 200 (Healthy)\n' "Health"
|
||||||
|
pass=$((pass + 1))
|
||||||
|
else
|
||||||
|
printf '%-28s not healthy\n' "Health"
|
||||||
|
fail=$((fail + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
check_post() {
|
check_post() {
|
||||||
path="$1"
|
path="$1"
|
||||||
expected="$2"
|
expected="$2"
|
||||||
@@ -184,7 +200,7 @@ check_post() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check "/dashboard" "200" "Dashboard"
|
check "/dashboard" "200" "Dashboard"
|
||||||
check "/health" "200" "Health"
|
check_health
|
||||||
check "/api/v1/operations/snapshot" "401" "Operations auth"
|
check "/api/v1/operations/snapshot" "401" "Operations auth"
|
||||||
check_post "/api/v1/chat" "401" "Chat auth"
|
check_post "/api/v1/chat" "401" "Chat auth"
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ jobs:
|
|||||||
JWT_AUDIENCE=nexus-web
|
JWT_AUDIENCE=nexus-web
|
||||||
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
||||||
BOOTSTRAP_OWNER_PASSWORD=${ENV_BOOTSTRAP_OWNER_PASSWORD:-}
|
BOOTSTRAP_OWNER_PASSWORD=${ENV_BOOTSTRAP_OWNER_PASSWORD:-}
|
||||||
OPENCLAW_BASE_URL=http://host.docker.internal:18789
|
OPENCLAW_BASE_URL=http://openclaw-gateway:18789
|
||||||
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN}
|
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN}
|
||||||
OPENCLAW_GATEWAY_PASSWORD=
|
OPENCLAW_GATEWAY_PASSWORD=
|
||||||
EOF
|
EOF
|
||||||
@@ -188,9 +188,10 @@ jobs:
|
|||||||
WAIT=1
|
WAIT=1
|
||||||
while [ $RETRY -lt $MAX ]; do
|
while [ $RETRY -lt $MAX ]; do
|
||||||
RETRY=$((RETRY + 1))
|
RETRY=$((RETRY + 1))
|
||||||
if curl -sf --max-time 10 https://nexus.noveria.net/health; then
|
HEALTH_BODY=$(curl -sf --max-time 10 https://nexus.noveria.net/health || true)
|
||||||
|
if printf '%s' "$HEALTH_BODY" | grep -Eq '^[[:space:]]*\{[[:space:]]*"status"[[:space:]]*:[[:space:]]*"Healthy"'; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "✅ Health check passed (attempt $RETRY/$MAX)"
|
echo "✅ Health check passed with Healthy runtime and database state (attempt $RETRY/$MAX)"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
echo "⏳ Attempt $RETRY/$MAX failed, waiting ${WAIT}s..."
|
echo "⏳ Attempt $RETRY/$MAX failed, waiting ${WAIT}s..."
|
||||||
@@ -225,8 +226,21 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_health() {
|
||||||
|
local body
|
||||||
|
body=$(curl -sf --max-time 10 "${BASE}/health" || true)
|
||||||
|
printf " %-25s" "Health API:"
|
||||||
|
if printf '%s' "$body" | grep -Eq '^[[:space:]]*\{[[:space:]]*"status"[[:space:]]*:[[:space:]]*"Healthy"'; then
|
||||||
|
echo " HTTP 200 Healthy ✅"
|
||||||
|
PASS=$((PASS + 1))
|
||||||
|
else
|
||||||
|
echo " not healthy ❌"
|
||||||
|
FAIL=$((FAIL + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
check "/dashboard" "Dashboard" 200
|
check "/dashboard" "Dashboard" 200
|
||||||
check "/health" "Health API" 200
|
check_health
|
||||||
check "/api/v1/operations/snapshot" "Operations API (auth)" 401
|
check "/api/v1/operations/snapshot" "Operations API (auth)" 401
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Nexus.Api.Data;
|
||||||
|
using Nexus.Api.Integrations;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Nexus.Api.Tests;
|
||||||
|
|
||||||
|
public sealed class OpenClawRuntimeTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task GetStatusAsync_BlankPasswordFallsBackToConfiguredToken()
|
||||||
|
{
|
||||||
|
string? authorization = null;
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||||
|
{
|
||||||
|
["Integrations:OpenClaw:Password"] = string.Empty,
|
||||||
|
["Integrations:OpenClaw:Token"] = "gateway-token"
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
var client = new HttpClient(new StubHandler(request =>
|
||||||
|
{
|
||||||
|
authorization = request.Headers.Authorization?.ToString();
|
||||||
|
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri("http://openclaw-gateway:18789")
|
||||||
|
};
|
||||||
|
var runtime = new OpenClawRuntime(client, configuration);
|
||||||
|
|
||||||
|
var status = await runtime.GetStatusAsync(CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(OperationalStatus.Online, status.Status);
|
||||||
|
Assert.Equal("Bearer gateway-token", authorization);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class StubHandler(
|
||||||
|
Func<HttpRequestMessage, HttpResponseMessage> responder) : HttpMessageHandler
|
||||||
|
{
|
||||||
|
protected override Task<HttpResponseMessage> SendAsync(
|
||||||
|
HttpRequestMessage request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
=> Task.FromResult(responder(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,8 +32,9 @@ public sealed class OpenClawRuntime(HttpClient client, IConfiguration configurat
|
|||||||
|
|
||||||
private void ApplyAuthorization(HttpRequestMessage request)
|
private void ApplyAuthorization(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
var credential = configuration["Integrations:OpenClaw:Password"]
|
var credential = configuration["Integrations:OpenClaw:Password"];
|
||||||
?? configuration["Integrations:OpenClaw:Token"];
|
if (string.IsNullOrWhiteSpace(credential))
|
||||||
|
credential = configuration["Integrations:OpenClaw:Token"];
|
||||||
if (!string.IsNullOrWhiteSpace(credential))
|
if (!string.IsNullOrWhiteSpace(credential))
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", credential);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", credential);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ services:
|
|||||||
ForwardedHeaders__ForwardLimit: ${FORWARDED_HEADERS_FORWARD_LIMIT:-1}
|
ForwardedHeaders__ForwardLimit: ${FORWARDED_HEADERS_FORWARD_LIMIT:-1}
|
||||||
ForwardedHeaders__KnownProxies__0: ${FORWARDED_HEADERS_KNOWN_PROXY:-}
|
ForwardedHeaders__KnownProxies__0: ${FORWARDED_HEADERS_KNOWN_PROXY:-}
|
||||||
ForwardedHeaders__KnownNetworks__0: ${FORWARDED_HEADERS_KNOWN_NETWORK:-}
|
ForwardedHeaders__KnownNetworks__0: ${FORWARDED_HEADERS_KNOWN_NETWORK:-}
|
||||||
Integrations__OpenClaw__BaseUrl: ${OPENCLAW_BASE_URL:-http://host.docker.internal:18789}
|
Integrations__OpenClaw__BaseUrl: ${OPENCLAW_BASE_URL:-http://openclaw-gateway:18789}
|
||||||
Integrations__OpenClaw__RequiredVersion: ${OPENCLAW_REQUIRED_VERSION:-2026.7.1}
|
Integrations__OpenClaw__RequiredVersion: ${OPENCLAW_REQUIRED_VERSION:-2026.7.1}
|
||||||
Integrations__OpenClaw__Token: ${OPENCLAW_GATEWAY_TOKEN:-}
|
Integrations__OpenClaw__Token: ${OPENCLAW_GATEWAY_TOKEN:-}
|
||||||
Integrations__OpenClaw__Password: ${OPENCLAW_GATEWAY_PASSWORD:-}
|
Integrations__OpenClaw__Password: ${OPENCLAW_GATEWAY_PASSWORD:-}
|
||||||
|
|||||||
Reference in New Issue
Block a user