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`.
|
||||
*Проверка:* 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`.
|
||||
*Проверка:* CI job `openapi`.
|
||||
|
||||
@@ -73,6 +73,15 @@ alwaysApply: false
|
||||
**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`.
|
||||
*Проверка:* review.
|
||||
|
||||
@@ -95,15 +104,23 @@ Tailwind v4: https://shadcn-svelte.com/docs/migration/tailwind-v4
|
||||
|
||||
## Enforcement
|
||||
|
||||
**Обязательный финальный шаг агента при правках `web/**`:** `npm run check` **и** `npm run lint` (см. **WEB-19**). Только `check` недостаточно.
|
||||
|
||||
```powershell
|
||||
cd web
|
||||
npm run check
|
||||
npm run lint
|
||||
# при warn/fail lint:
|
||||
npx prettier --write .
|
||||
npm run check
|
||||
npm run lint
|
||||
```
|
||||
|
||||
**PR checklist `web/**`:**
|
||||
- [ ] `npm run check` — exit 0
|
||||
- [ ] `npm run lint` (prettier --check) — exit 0
|
||||
- [ ] `ui/core` / `ui/patterns`, не дубли примитивов
|
||||
- [ ] Новые примитивы через shadcn CLI
|
||||
- [ ] Ссылка на docs компонента (если новый паттерн)
|
||||
|
||||
**CI:** job `web` рекомендован; пока обязательно локально.
|
||||
**CI:** job `web` — `npm run check` + `npm run lint`.
|
||||
|
||||
@@ -58,4 +58,12 @@
|
||||
|
||||
## 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 run dev
|
||||
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/`):
|
||||
|
||||
```sh
|
||||
|
||||
@@ -125,7 +125,9 @@
|
||||
agent_domain: s.agent_domain ?? '',
|
||||
node_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 {
|
||||
const ep =
|
||||
f.endpoint.trim() ||
|
||||
(f.agent_domain.trim() ? `https://${f.agent_domain.trim()}` : '');
|
||||
f.endpoint.trim() || (f.agent_domain.trim() ? `https://${f.agent_domain.trim()}` : '');
|
||||
return {
|
||||
endpoint: ep,
|
||||
role: f.role.trim() || 'replica',
|
||||
@@ -294,7 +295,9 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<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 class="flex shrink-0 flex-wrap items-center justify-end gap-2">
|
||||
<Button size="sm" onclick={openCreate}><Plus />Добавить</Button>
|
||||
@@ -352,11 +355,7 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
||||
</DialogHeader>
|
||||
<div class="space-y-4 py-2">
|
||||
<FormField label="Agent domain (FQDN)" id="s-domain">
|
||||
<AppInput
|
||||
id="s-domain"
|
||||
placeholder="bgp-dc2.example.com"
|
||||
bind:value={form.agent_domain}
|
||||
/>
|
||||
<AppInput id="s-domain" placeholder="bgp-dc2.example.com" bind:value={form.agent_domain} />
|
||||
</FormField>
|
||||
<FormField label="Endpoint" id="s-endpoint">
|
||||
<AppInput
|
||||
@@ -410,7 +409,12 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
||||
{#if createdSpeaker?.agent_secret}
|
||||
<FormField label="agent_secret (один раз)" id="w-secret">
|
||||
<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>
|
||||
</div>
|
||||
</FormField>
|
||||
@@ -449,7 +453,9 @@ CF_DNS_API_TOKEN=<cloudflare token>
|
||||
<DialogContent class="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Copy docker-compose</DialogTitle>
|
||||
<DialogDescription>Спикер {composeTarget?.agent_domain ?? composeTarget?.id}</DialogDescription>
|
||||
<DialogDescription
|
||||
>Спикер {composeTarget?.agent_domain ?? composeTarget?.id}</DialogDescription
|
||||
>
|
||||
</DialogHeader>
|
||||
<textarea
|
||||
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