docs: update guidelines for Svelte module changes and linting requirements
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been cancelled
CI / web (push) Has been cancelled
CI / go (push) Has been cancelled
CI / bird2 (push) Has been cancelled
CI / release (push) Has been cancelled
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been cancelled
CI / web (push) Has been cancelled
CI / go (push) Has been cancelled
CI / bird2 (push) Has been cancelled
CI / release (push) Has been cancelled
- Enhanced documentation in AGENTS.md and web/README.md to clarify the mandatory steps for running `npm run check` and `npm run lint` before finalizing changes in the `web/**` directory. - Updated engineering rules in .cursor/rules/engineering.mdc to specify the necessity of both commands and the use of Prettier for formatting issues. - Added detailed instructions for handling linting failures and emphasized the importance of these checks in CI workflows.
This commit is contained in:
@@ -123,8 +123,8 @@ alwaysApply: true
|
|||||||
**TEST-03** | MUST | Новые BIRD-сценарии в `internal/birdfmt/testdata/scenarios/*/bird.conf` + `bird -p`.
|
**TEST-03** | MUST | Новые BIRD-сценарии в `internal/birdfmt/testdata/scenarios/*/bird.conf` + `bird -p`.
|
||||||
*Проверка:* CI job `bird2`.
|
*Проверка:* CI job `bird2`.
|
||||||
|
|
||||||
**TEST-04** | MUST | Изменения `web/` — локально `npm run check` и `npm run lint`; CI job `web` в `.gitea/workflows/ci.yaml`.
|
**TEST-04** | MUST | Изменения `web/` — локально **`npm run check` и `npm run lint`** (обе команды, exit 0); CI job `web` в `.gitea/workflows/ci.yaml`. Агент: при fail lint — `npx prettier --write` затем повтор. Только `check` не заменяет `lint`.
|
||||||
*Проверка:* локальные команды.
|
*Проверка:* CI job `web`; `.cursor/rules/web-shadcn.mdc` WEB-19.
|
||||||
|
|
||||||
**TEST-05** | MUST | Изменения OpenAPI — `npx @redocly/cli lint docs/openapi.yaml`.
|
**TEST-05** | MUST | Изменения OpenAPI — `npx @redocly/cli lint docs/openapi.yaml`.
|
||||||
*Проверка:* CI job `openapi`.
|
*Проверка:* CI job `openapi`.
|
||||||
|
|||||||
@@ -73,6 +73,15 @@ alwaysApply: false
|
|||||||
**WEB-15** | MUST | Сомнения — https://shadcn-svelte.com/llms.txt , Svelte MCP, `npm run check`.
|
**WEB-15** | MUST | Сомнения — https://shadcn-svelte.com/llms.txt , Svelte MCP, `npm run check`.
|
||||||
*Проверка:* локально.
|
*Проверка:* локально.
|
||||||
|
|
||||||
|
**WEB-19** | MUST | **После любого изменения `web/**`** — перед завершением задачи агент **обязан** выполнить в `web/`:
|
||||||
|
```powershell
|
||||||
|
npm run check
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
Если `npm run lint` падает (Prettier) — **сначала** `npx prettier --write <изменённые файлы>` или `npx prettier --write .`, затем снова `npm run check` и `npm run lint`. Не сдавать PR/ответ, пока обе команды не exit 0.
|
||||||
|
*Rationale:* CI job `web` = `check` + `prettier --check`; `svelte-check` не ловит форматирование.
|
||||||
|
*Проверка:* CI job `web`; pre-commit hook `prettier-web`.
|
||||||
|
|
||||||
**WEB-16** | MUST | Подтверждение удаления — `ConfirmDialog` из patterns, не `window.confirm`.
|
**WEB-16** | MUST | Подтверждение удаления — `ConfirmDialog` из patterns, не `window.confirm`.
|
||||||
*Проверка:* review.
|
*Проверка:* review.
|
||||||
|
|
||||||
@@ -95,15 +104,23 @@ Tailwind v4: https://shadcn-svelte.com/docs/migration/tailwind-v4
|
|||||||
|
|
||||||
## Enforcement
|
## Enforcement
|
||||||
|
|
||||||
|
**Обязательный финальный шаг агента при правках `web/**`:** `npm run check` **и** `npm run lint` (см. **WEB-19**). Только `check` недостаточно.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd web
|
cd web
|
||||||
npm run check
|
npm run check
|
||||||
npm run lint
|
npm run lint
|
||||||
|
# при warn/fail lint:
|
||||||
|
npx prettier --write .
|
||||||
|
npm run check
|
||||||
|
npm run lint
|
||||||
```
|
```
|
||||||
|
|
||||||
**PR checklist `web/**`:**
|
**PR checklist `web/**`:**
|
||||||
|
- [ ] `npm run check` — exit 0
|
||||||
|
- [ ] `npm run lint` (prettier --check) — exit 0
|
||||||
- [ ] `ui/core` / `ui/patterns`, не дубли примитивов
|
- [ ] `ui/core` / `ui/patterns`, не дубли примитивов
|
||||||
- [ ] Новые примитивы через shadcn CLI
|
- [ ] Новые примитивы через shadcn CLI
|
||||||
- [ ] Ссылка на docs компонента (если новый паттерн)
|
- [ ] Ссылка на docs компонента (если новый паттерн)
|
||||||
|
|
||||||
**CI:** job `web` рекомендован; пока обязательно локально.
|
**CI:** job `web` — `npm run check` + `npm run lint`.
|
||||||
|
|||||||
@@ -58,4 +58,12 @@
|
|||||||
|
|
||||||
## Svelte / фронтенд
|
## Svelte / фронтенд
|
||||||
|
|
||||||
При правках `web/**/*.svelte` или Svelte-модулей следуйте навыкам/инструментам проекта (официальный Svelte MCP и скиллы Cursor, если подключены).
|
При правках `web/**/*.svelte` или Svelte-модулей следуйте [.cursor/rules/web-shadcn.mdc](.cursor/rules/web-shadcn.mdc) (**WEB-19**): перед завершением задачи **обязательно**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd web
|
||||||
|
npm run check
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
Если `lint` падает — `npx prettier --write .` и повторить обе команды. CI job `web` не пропускает без этого.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Same gates as CI job web (.gitea/workflows/ci.yaml).
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
Set-Location (Join-Path $PSScriptRoot '..' 'web')
|
||||||
|
npm run check
|
||||||
|
npm run lint
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Same gates as CI job web (.gitea/workflows/ci.yaml).
|
||||||
|
set -euxo pipefail
|
||||||
|
cd "$(dirname "$0")/../web"
|
||||||
|
npm run check
|
||||||
|
npm run lint
|
||||||
@@ -21,8 +21,21 @@ SvelteKit-приложение панели управления EvoBGP. Зап
|
|||||||
npm install
|
npm install
|
||||||
npm run dev
|
npm run dev
|
||||||
npm run check
|
npm run check
|
||||||
|
npm run lint # prettier --check; обязательно перед PR (CI job web)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Из корня репозитория (обе проверки как в CI):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -NoProfile -File scripts/lint-web.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sh scripts/lint-web.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
При падении `lint`: `npx prettier --write .` в каталоге `web/`, затем снова `check` + `lint`.
|
||||||
|
|
||||||
Добавление компонентов shadcn (из каталога `web/`):
|
Добавление компонентов shadcn (из каталога `web/`):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -125,7 +125,9 @@
|
|||||||
agent_domain: s.agent_domain ?? '',
|
agent_domain: s.agent_domain ?? '',
|
||||||
node_ipv4: s.node_ipv4 ?? '',
|
node_ipv4: s.node_ipv4 ?? '',
|
||||||
bird_bgp_source_ipv4: s.bird_bgp_source_ipv4 ?? s.node_ipv4 ?? '',
|
bird_bgp_source_ipv4: s.bird_bgp_source_ipv4 ?? s.node_ipv4 ?? '',
|
||||||
bgpSourceManual: Boolean(s.bird_bgp_source_ipv4 && s.node_ipv4 && s.bird_bgp_source_ipv4 !== s.node_ipv4)
|
bgpSourceManual: Boolean(
|
||||||
|
s.bird_bgp_source_ipv4 && s.node_ipv4 && s.bird_bgp_source_ipv4 !== s.node_ipv4
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +141,7 @@
|
|||||||
|
|
||||||
function buildApiBody(f: SpeakerForm): BgpSpeakerCreate {
|
function buildApiBody(f: SpeakerForm): BgpSpeakerCreate {
|
||||||
const ep =
|
const ep =
|
||||||
f.endpoint.trim() ||
|
f.endpoint.trim() || (f.agent_domain.trim() ? `https://${f.agent_domain.trim()}` : '');
|
||||||
(f.agent_domain.trim() ? `https://${f.agent_domain.trim()}` : '');
|
|
||||||
return {
|
return {
|
||||||
endpoint: ep,
|
endpoint: ep,
|
||||||
role: f.role.trim() || 'replica',
|
role: f.role.trim() || 'replica',
|
||||||
@@ -294,7 +295,9 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
|||||||
>
|
>
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<CardTitle class="text-base">Спикеры</CardTitle>
|
<CardTitle class="text-base">Спикеры</CardTitle>
|
||||||
<CardDescription>Удалённые BIRD-ноды (Remnawave-style Panel→Node + signed bundle)</CardDescription>
|
<CardDescription
|
||||||
|
>Удалённые BIRD-ноды (Remnawave-style Panel→Node + signed bundle)</CardDescription
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
|
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
|
||||||
<Button size="sm" onclick={openCreate}><Plus />Добавить</Button>
|
<Button size="sm" onclick={openCreate}><Plus />Добавить</Button>
|
||||||
@@ -352,11 +355,7 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div class="space-y-4 py-2">
|
<div class="space-y-4 py-2">
|
||||||
<FormField label="Agent domain (FQDN)" id="s-domain">
|
<FormField label="Agent domain (FQDN)" id="s-domain">
|
||||||
<AppInput
|
<AppInput id="s-domain" placeholder="bgp-dc2.example.com" bind:value={form.agent_domain} />
|
||||||
id="s-domain"
|
|
||||||
placeholder="bgp-dc2.example.com"
|
|
||||||
bind:value={form.agent_domain}
|
|
||||||
/>
|
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Endpoint" id="s-endpoint">
|
<FormField label="Endpoint" id="s-endpoint">
|
||||||
<AppInput
|
<AppInput
|
||||||
@@ -410,7 +409,12 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
|||||||
{#if createdSpeaker?.agent_secret}
|
{#if createdSpeaker?.agent_secret}
|
||||||
<FormField label="agent_secret (один раз)" id="w-secret">
|
<FormField label="agent_secret (один раз)" id="w-secret">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<AppInput id="w-secret" readonly value={createdSpeaker.agent_secret} class="font-mono text-xs" />
|
<AppInput
|
||||||
|
id="w-secret"
|
||||||
|
readonly
|
||||||
|
value={createdSpeaker.agent_secret}
|
||||||
|
class="font-mono text-xs"
|
||||||
|
/>
|
||||||
<Button variant="outline" size="icon-sm" onclick={copyAgentSecret}><Copy /></Button>
|
<Button variant="outline" size="icon-sm" onclick={copyAgentSecret}><Copy /></Button>
|
||||||
</div>
|
</div>
|
||||||
</FormField>
|
</FormField>
|
||||||
@@ -449,7 +453,9 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
|||||||
<DialogContent class="sm:max-w-lg">
|
<DialogContent class="sm:max-w-lg">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Copy docker-compose</DialogTitle>
|
<DialogTitle>Copy docker-compose</DialogTitle>
|
||||||
<DialogDescription>Спикер {composeTarget?.agent_domain ?? composeTarget?.id}</DialogDescription>
|
<DialogDescription
|
||||||
|
>Спикер {composeTarget?.agent_domain ?? composeTarget?.id}</DialogDescription
|
||||||
|
>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<textarea
|
<textarea
|
||||||
class="min-h-[240px] w-full rounded-md border bg-muted/30 p-2 font-mono text-xs"
|
class="min-h-[240px] w-full rounded-md border bg-muted/30 p-2 font-mono text-xs"
|
||||||
|
|||||||
Reference in New Issue
Block a user