Add release traceability guidance and ping metadata

This commit is contained in:
Haitao Pan 2026-04-12 15:47:24 +08:00
parent 68102491e2
commit c94257e06c
4 changed files with 80 additions and 14 deletions

View File

@ -51,7 +51,20 @@ yarn test:e2e path/to/spec.test.ts
---
## 2. Repository Mental Model (Read This First)
## 2. Release Traceability Default Rule
For any change touching CI/CD, image tags, deploy contracts, `/api/ping`, or `validate` behavior:
- Treat `skills/release-traceability/SKILL.md` as the default reference before implementation.
- Prefer release metadata that can be traced from `build` to `deploy` to `validate` without manual injection.
- Keep the published image reference, runtime version, and validation output aligned.
- Do not introduce a deploy path that rebuilds images on the target host.
When in doubt, follow the skill first and keep the release chain fully auditable end to end.
---
## 3. Repository Mental Model (Read This First)
This repository has **three clearly separated layers**:
@ -91,7 +104,7 @@ Used for build-time or runtime wiring only.
---
## 3. Import & Alias Rules (Critical)
## 4. Import & Alias Rules (Critical)
### Dashboard code (src/\*\*)
@ -112,7 +125,7 @@ import { UserCard } from "@/components/UserCard";
---
## 4. TypeScript & Formatting Rules
## 5. TypeScript & Formatting Rules
- Strict mode enabled
- Use `type` for type definitions, `interface` for object shapes
@ -123,7 +136,7 @@ import { UserCard } from "@/components/UserCard";
---
## 5. Naming Conventions
## 6. Naming Conventions
- Components: PascalCase (`UserProfile.tsx`)
- Files: kebab-case for utilities (`user-utils.ts`), PascalCase for components
@ -133,7 +146,7 @@ import { UserCard } from "@/components/UserCard";
---
## 6. Error Handling & Logging
## 7. Error Handling & Logging
- Use try/catch for async operations
- Return Result types or throw errors consistently
@ -142,7 +155,7 @@ import { UserCard } from "@/components/UserCard";
---
## 7. React Patterns
## 8. React Patterns
- Use `'use client'` directive for client components
- Prefer function components with hooks
@ -151,7 +164,7 @@ import { UserCard } from "@/components/UserCard";
---
## 8. Global State Rules (Dashboard Only)
## 9. Global State Rules (Dashboard Only)
✅ Zustand is the **only** allowed global state mechanism
❌ React Context for shared/global state is forbidden
@ -162,7 +175,7 @@ Rule: If state must survive navigation or be shared → it lives in Zustand.
---
## 9. URL-Synchronized State
## 10. URL-Synchronized State
Anything involving:
@ -179,7 +192,7 @@ MUST be handled inside Zustand slices.
---
## 10. Component State Rules
## 11. Component State Rules
Allowed:
@ -194,7 +207,7 @@ Forbidden:
---
## 11. packages/neurapress Rules (Very Important)
## 12. packages/neurapress Rules (Very Important)
packages/neurapress is treated as a vendored internal library.
@ -214,7 +227,7 @@ MUST NOT:
---
## 12. Testing Guidelines
## 13. Testing Guidelines
- Unit tests: Vitest with jsdom environment
- E2E tests: Playwright
@ -224,7 +237,7 @@ MUST NOT:
---
## 13. Environment & Runtime Config
## 14. Environment & Runtime Config
- No new environment variables without approval
- Runtime config must live in: src/config/runtime-service-config\*.yaml
@ -233,13 +246,13 @@ MUST NOT:
---
## 14. Cursor / Copilot Rules
## 15. Cursor / Copilot Rules
- No `.cursor/rules/`, `.cursorrules`, or `.github/copilot-instructions.md` found
---
## 15. TL;DR for AI Agents
## 16. TL;DR for AI Agents
- dashboard = application
- packages = libraries

View File

@ -16,6 +16,12 @@ You are an AI agent working inside this repository.
- Keep changes scoped to the request; avoid unrelated refactors.
- Prefer minimal edits that preserve existing behavior and style.
## Release Traceability Default Rule
- For changes touching CI/CD, image tags, deploy contracts, `/api/ping`, or `validate`, treat `skills/release-traceability/SKILL.md` as the default reference first.
- Keep build output, runtime version, and validate output aligned through the whole release chain.
- Do not add a deploy path that rebuilds images on the target host.
## Repository Constraints (Quick View)
- App layer: src/app/**, src/components/**, src/lib/**, src/state/**, src/modules/\*\*

View File

@ -0,0 +1,32 @@
---
name: release-traceability
description: Default reference for release-traceability work in this repository. Use when changing CI/CD, image tags, deploy contracts, /api/ping, validate, or any build-to-deploy-to-verify release path.
---
# Release Traceability
## Default Rule
When working on release flow changes in this repository, treat this skill as the first reference.
## Scope
Use for:
- CI/CD orchestration
- Image tag and image reference generation
- Deploy contract changes
- `/api/ping` release metadata
- `validate` release verification
## Required Invariants
- Build output must carry a traceable commit-based version.
- Deploy must consume the published image only.
- Target hosts must not rebuild images.
- `/api/ping` must expose the active release identity.
- `validate` must compare build output, runtime output, and deployed image metadata.
## Working Rule
Prefer the simplest implementation that keeps the release chain auditable from commit to build artifact to runtime verification.

View File

@ -2,9 +2,23 @@ import { NextResponse } from 'next/server'
import { loadRuntimeConfig } from '@server/runtime-loader'
function resolveReleaseImageMetadata(frontendImage: string | undefined) {
const releaseImageRef = frontendImage?.trim() || null
const releaseImageTagMatch = releaseImageRef?.match(/:([^:@]+)$/)
const releaseImageTag = releaseImageTagMatch?.[1] ?? null
const releaseCommit = releaseImageTag && /^[0-9a-f]{7,40}$/i.test(releaseImageTag) ? releaseImageTag : null
return {
releaseImageRef,
releaseImageTag,
releaseCommit,
}
}
export async function GET(request: Request) {
const hostnameHeader = request.headers.get('host') ?? undefined
const runtimeConfig = loadRuntimeConfig({ hostname: hostnameHeader })
const releaseMetadata = resolveReleaseImageMetadata(process.env.FRONTEND_IMAGE)
const payload = {
status: 'ok' as const,
@ -14,6 +28,7 @@ export async function GET(request: Request) {
authUrl: runtimeConfig.authUrl,
dashboardUrl: runtimeConfig.dashboardUrl,
logLevel: runtimeConfig.logLevel,
...releaseMetadata,
}
console.info('[runtime-config] /api/ping resolved config snippet', payload)