feat(platform): expose deployed release
This commit is contained in:
@@ -57,6 +57,7 @@ func NewServer(cfg config.Config) http.Handler {
|
||||
AMapSecurityProxyEnabled: strings.TrimSpace(cfg.AMapSecurityCode) != "" && strings.TrimSpace(cfg.AMapServiceHost) != "",
|
||||
AMapSecurityCodeExposed: exposedAMapSecurityCode(cfg) != "",
|
||||
AMapSecurityServiceHost: strings.TrimSpace(cfg.AMapServiceHost),
|
||||
PlatformRelease: strings.TrimSpace(cfg.PlatformRelease),
|
||||
}))
|
||||
handler := static.Handler(cfg.StaticDir, api)
|
||||
handler = withAppConfig(handler, cfg)
|
||||
|
||||
@@ -23,6 +23,7 @@ type Config struct {
|
||||
AMapWebJSKey string
|
||||
AMapSecurityCode string
|
||||
AMapServiceHost string
|
||||
PlatformRelease string
|
||||
}
|
||||
|
||||
func Load() Config {
|
||||
@@ -43,6 +44,7 @@ func Load() Config {
|
||||
AMapWebJSKey: os.Getenv("AMAP_WEB_JS_KEY"),
|
||||
AMapSecurityCode: os.Getenv("AMAP_SECURITY_JS_CODE"),
|
||||
AMapServiceHost: os.Getenv("AMAP_SECURITY_SERVICE_HOST"),
|
||||
PlatformRelease: os.Getenv("PLATFORM_RELEASE"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,3 +14,13 @@ func TestLoadReadsRequestTimeout(t *testing.T) {
|
||||
t.Fatalf("RequestTimeout = %s, want 1.2s", cfg.RequestTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadReadsPlatformRelease(t *testing.T) {
|
||||
t.Setenv("PLATFORM_RELEASE", "platform-20260704153005")
|
||||
|
||||
cfg := Load()
|
||||
|
||||
if cfg.PlatformRelease != "platform-20260704153005" {
|
||||
t.Fatalf("PlatformRelease = %q", cfg.PlatformRelease)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,6 +895,7 @@ func TestHandlerOpsHealthIncludesVehicleServiceRuntime(t *testing.T) {
|
||||
AMapSecurityProxyEnabled: true,
|
||||
AMapSecurityCodeExposed: false,
|
||||
AMapSecurityServiceHost: "/_AMapService",
|
||||
PlatformRelease: "platform-20260704153005",
|
||||
}))
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/ops/health", nil)
|
||||
@@ -920,6 +921,9 @@ func TestHandlerOpsHealthIncludesVehicleServiceRuntime(t *testing.T) {
|
||||
if body.Data.Runtime.AMapSecurityServiceHost != "/_AMapService" {
|
||||
t.Fatalf("ops health should include AMap security service host, got %+v", body.Data.Runtime)
|
||||
}
|
||||
if body.Data.Runtime.PlatformRelease != "platform-20260704153005" {
|
||||
t.Fatalf("ops health should include platform release, got %+v", body.Data.Runtime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlerVehicleDataAPIsResolveVehicleKeyword(t *testing.T) {
|
||||
|
||||
@@ -349,4 +349,5 @@ type RuntimeInfo struct {
|
||||
AMapSecurityProxyEnabled bool `json:"amapSecurityProxyEnabled"`
|
||||
AMapSecurityCodeExposed bool `json:"amapSecurityCodeExposed"`
|
||||
AMapSecurityServiceHost string `json:"amapSecurityServiceHost"`
|
||||
PlatformRelease string `json:"platformRelease"`
|
||||
}
|
||||
|
||||
@@ -338,6 +338,7 @@ export interface RuntimeInfo {
|
||||
amapSecurityProxyEnabled?: boolean;
|
||||
amapSecurityCodeExposed?: boolean;
|
||||
amapSecurityServiceHost?: string;
|
||||
platformRelease?: string;
|
||||
}
|
||||
|
||||
export interface Page<T> {
|
||||
|
||||
@@ -294,6 +294,12 @@ export function Realtime({
|
||||
color: amapSecurityCodeExposed ? 'red' as const : 'green' as const,
|
||||
detail: amapSecurityCodeExposed ? '当前安全码会下发到浏览器,只建议调试使用。' : '生产安全码保持在服务端环境变量中。'
|
||||
},
|
||||
{
|
||||
label: '当前版本',
|
||||
value: runtime?.platformRelease || '未标记',
|
||||
color: runtime?.platformRelease ? 'blue' as const : 'grey' as const,
|
||||
detail: runtime?.platformRelease ? '当前 ECS 正在运行的车辆中台 release。' : '未注入 PLATFORM_RELEASE,部署追踪会降级。'
|
||||
},
|
||||
{
|
||||
label: '定位覆盖',
|
||||
value: `${locatedCount.toLocaleString()} / ${rows.length.toLocaleString()}`,
|
||||
|
||||
@@ -7476,7 +7476,8 @@ test('shows production AMap integration status on realtime page', async () => {
|
||||
amapWebJsConfigured: true,
|
||||
amapSecurityProxyEnabled: true,
|
||||
amapSecurityCodeExposed: false,
|
||||
amapSecurityServiceHost: '/_AMapService'
|
||||
amapSecurityServiceHost: '/_AMapService',
|
||||
platformRelease: 'platform-20260704153005'
|
||||
}
|
||||
},
|
||||
traceId: 'trace-test',
|
||||
@@ -7557,6 +7558,8 @@ test('shows production AMap integration status on realtime page', async () => {
|
||||
expect(screen.getAllByText('已配置').length).toBeGreaterThan(0);
|
||||
expect(screen.getByText('安全代理')).toBeInTheDocument();
|
||||
expect(screen.getByText('/_AMapService')).toBeInTheDocument();
|
||||
expect(screen.getByText('当前版本')).toBeInTheDocument();
|
||||
expect(screen.getByText('platform-20260704153005')).toBeInTheDocument();
|
||||
expect(screen.getByText('定位覆盖')).toBeInTheDocument();
|
||||
expect(screen.getByText('1 / 2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -39,10 +39,13 @@ REQUEST_TIMEOUT_MS=5000
|
||||
AMAP_WEB_JS_KEY=***
|
||||
AMAP_SECURITY_JS_CODE=***
|
||||
AMAP_SECURITY_SERVICE_HOST=/_AMapService
|
||||
PLATFORM_RELEASE=platform-YYYYMMDDHHMMSS
|
||||
```
|
||||
|
||||
`AMAP_WEB_JS_KEY` is served to the browser through `/app-config.js` so the same static build can be reused across environments. For production, set both `AMAP_SECURITY_JS_CODE` and `AMAP_SECURITY_SERVICE_HOST=/_AMapService`; the API service keeps the security code on the server and proxies AMap requests with `jscode` appended. Only omit `AMAP_SECURITY_SERVICE_HOST` for controlled debugging where exposing `AMAP_SECURITY_JS_CODE` to the browser is acceptable.
|
||||
|
||||
`PLATFORM_RELEASE` is surfaced by `/api/ops/health.runtime.platformRelease` so operators can confirm which ECS release is currently active after a deployment.
|
||||
|
||||
## Health
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user