10 Commits
Author SHA1 Message Date
ksv741 3c99debe88 chore(release): 0.3.0
Frontend image / publish (push) Successful in 5m45s
Conventional commits / commits (pull_request) Successful in 27s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 4m42s
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 6m17s
2026-09-20 20:09:11 +03:00
ksv741 bb30935f73 feat: add installable PWA #30
Conventional commits / commits (pull_request) Successful in 30s
Frontend security / security (pull_request) Successful in 1m7s
Frontend verify / verify (pull_request) Successful in 4m48s
Frontend security / security (push) Successful in 11s
Frontend verify / verify (push) Successful in 6m17s
2026-09-20 19:55:53 +03:00
ksv741 f486ae4fb2 chore(release): 0.2.3
Frontend image / publish (push) Successful in 4m51s
Conventional commits / commits (pull_request) Successful in 21s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 3m56s
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Successful in 5m27s
2026-09-19 16:25:12 +03:00
ksv741 9171b9f5c8 fix: correct Nexus routing and SonarQube host 2026-09-19 16:24:07 +03:00
ksv741 d68ec3b15b chore(release): 0.2.2
Frontend image / publish (push) Failing after 3m59s
Conventional commits / commits (pull_request) Successful in 20s
Frontend security / security (pull_request) Successful in 10s
Frontend verify / verify (pull_request) Successful in 4m5s
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Failing after 4m26s
2026-09-19 15:04:33 +03:00
ksv741 bac95ebb39 fix: update Nexus registry host
Conventional commits / commits (pull_request) Successful in 21s
Frontend security / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 4m11s
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Failing after 4m7s
2026-09-19 14:51:25 +03:00
ksv741 8183b66e2f chore(release): 0.2.1
Conventional commits / commits (pull_request) Successful in 20s
Frontend security / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 3m36s
Frontend image / publish (push) Failing after 3m56s
Frontend security / security (push) Successful in 8s
Frontend verify / verify (push) Failing after 4m13s
2026-09-18 08:12:21 +03:00
ksv741 1ad578fb37 docs: use shared Nexus account #21
Frontend security / security (pull_request) Successful in 53s
Frontend verify / verify (pull_request) Successful in 3m52s
Conventional commits / commits (pull_request) Successful in 20s
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Failing after 7m49s
2026-09-17 20:53:03 +03:00
ksv741 999b8590ec ci: publish frontend images to Nexus #21
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Successful in 3m57s
Conventional commits / commits (pull_request) Failing after 19s
Frontend security / security (pull_request) Successful in 32s
Frontend verify / verify (pull_request) Successful in 3m54s
2026-09-17 20:41:12 +03:00
ksv741 3f19b3643f ci: add frontend SonarQube analysis #19
Conventional commits / commits (pull_request) Successful in 22s
Frontend security / security (pull_request) Successful in 16s
Frontend verify / verify (pull_request) Successful in 3m59s
Frontend security / security (push) Successful in 18s
Frontend verify / verify (push) Successful in 9m45s
2026-09-16 20:08:51 +03:00
15 changed files with 4758 additions and 15 deletions
+5 -5
View File
@@ -12,7 +12,7 @@ jobs:
publish: publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
IMAGE: git.personal.ksv741.ru/wealthledger/frontend IMAGE: nexus.personal.ksv741.ru/docker-hosted/wealthledger/frontend
RELEASE_TAG: ${{ gitea.ref_name }} RELEASE_TAG: ${{ gitea.ref_name }}
REVISION: ${{ gitea.sha }} REVISION: ${{ gitea.sha }}
DOCKER_CONFIG: ${{ runner.temp }}/wealthledger-frontend-docker DOCKER_CONFIG: ${{ runner.temp }}/wealthledger-frontend-docker
@@ -33,14 +33,14 @@ jobs:
- run: npm run verify - run: npm run verify
env: env:
KNIP_DISABLE_RAW_TRANSFER: '1' KNIP_DISABLE_RAW_TRANSFER: '1'
- name: Login with dedicated package writer - name: Login with dedicated Nexus writer
env: env:
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_USERNAME: ${{ secrets.NEXUS_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} REGISTRY_TOKEN: ${{ secrets.NEXUS_PASSWORD }}
run: | run: |
test -n "$REGISTRY_USERNAME" && test -n "$REGISTRY_TOKEN" test -n "$REGISTRY_USERNAME" && test -n "$REGISTRY_TOKEN"
install -d -m 700 "$DOCKER_CONFIG" install -d -m 700 "$DOCKER_CONFIG"
printf '%s' "$REGISTRY_TOKEN" | docker login git.personal.ksv741.ru --username "$REGISTRY_USERNAME" --password-stdin printf '%s' "$REGISTRY_TOKEN" | docker login nexus.personal.ksv741.ru --username "$REGISTRY_USERNAME" --password-stdin
- name: Publish immutable release tag - name: Publish immutable release tag
run: | run: |
VERSION="${RELEASE_TAG#v}" VERSION="${RELEASE_TAG#v}"
+10
View File
@@ -11,6 +11,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: https://github.com/actions/checkout@v4 - uses: https://github.com/actions/checkout@v4
with:
fetch-depth: 0
- name: Record checked revision - name: Record checked revision
run: git rev-parse HEAD run: git rev-parse HEAD
- uses: https://github.com/actions/setup-node@v4 - uses: https://github.com/actions/setup-node@v4
@@ -24,3 +26,11 @@ jobs:
env: env:
# OXC raw transfer allocates a ~6 GiB buffer; use the standard parser in CI. # OXC raw transfer allocates a ~6 GiB buffer; use the standard parser in CI.
KNIP_DISABLE_RAW_TRANSFER: '1' KNIP_DISABLE_RAW_TRANSFER: '1'
- name: Analyze develop with SonarQube
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/develop'
# v2.3.0: Docker-based scanner for the SonarQube 9.9 server.
uses: https://github.com/SonarSource/sonarqube-scan-action@aecaf43ae57e412bd97d70ef9ce6076e672fe0a9
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: -Dsonar.qualitygate.wait=true
+1
View File
@@ -12,6 +12,7 @@ dist
storybook-static storybook-static
dist-ssr dist-ssr
coverage coverage
.scannerwork
*.local *.local
# Local runtime configuration # Local runtime configuration
+29
View File
@@ -1,5 +1,34 @@
# Changelog # Changelog
## [0.3.0](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.2.3...v0.3.0) (2026-09-20)
### Features
* add installable PWA [#30](https://git.personal.ksv741.ru/WealthLedger/frontend/issues/30) ([bb30935](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/bb30935f73bfcbb77c10663cf6c683d8f0caca85))
## [0.2.3](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.2.2...v0.2.3) (2026-09-19)
### Bug Fixes
* correct Nexus routing and SonarQube host ([9171b9f](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/9171b9f5c8e0b694a2310e5a200fa2f8d3f28a61))
## [0.2.2](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.2.1...v0.2.2) (2026-09-19)
### Bug Fixes
* update Nexus registry host ([bac95eb](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/bac95ebb392febb667a9fc2f1fa4f06fa110d685))
## [0.2.1](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.2.0...v0.2.1) (2026-09-18)
### Documentation
* use shared Nexus account [#21](https://git.personal.ksv741.ru/WealthLedger/frontend/issues/21) ([1ad578f](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/1ad578fb37b8dd6161dc362541d9c0cd0b008b75))
### CI
* add frontend SonarQube analysis [#19](https://git.personal.ksv741.ru/WealthLedger/frontend/issues/19) ([3f19b36](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/3f19b3643f88e36d10e7c374262351f61947ed47))
* publish frontend images to Nexus [#21](https://git.personal.ksv741.ru/WealthLedger/frontend/issues/21) ([999b859](https://git.personal.ksv741.ru/WealthLedger/frontend/commit/999b8590ecd0a551da628c349d005ebb9b318883))
## [0.2.0](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.1.0...v0.2.0) (2026-09-16) ## [0.2.0](https://git.personal.ksv741.ru/WealthLedger/frontend/compare/v0.1.0...v0.2.0) (2026-09-16)
### Features ### Features
+62 -4
View File
@@ -37,10 +37,13 @@ docker build --target production -t wealthledger-frontend:production .
Gitea `image.yml` запускается на защищённом release tag `vX.Y.Z`, проверяет Gitea `image.yml` запускается на защищённом release tag `vX.Y.Z`, проверяет
package/lock version и canonical gates. Runner `ubuntu-latest` должен иметь package/lock version и canonical gates. Runner `ubuntu-latest` должен иметь
Docker/buildx. Dedicated package writer задаётся Actions secrets Docker/buildx. Образы хранятся в Nexus:
`REGISTRY_USERNAME`/`REGISTRY_TOKEN`; server использует отдельную read-only `nexus.personal.ksv741.ru/docker-hosted/wealthledger/frontend`. Пользователь `wealthledger-ci`
identity. Публикуются semver tags, без `latest`; существующие задаётся Actions secrets `NEXUS_USERNAME`/`NEXUS_PASSWORD`; эта же учётная
release tags не перезаписываются. Production выбирает опубликованный version tag. запись используется сервером для загрузки образов. Docker endpoint и token realm должны использовать
HTTPS; в `docker-hosted` включается запрет redeploy. Прежние Gitea secrets
сохраняются на время перехода и не передаются в Nexus.
Публикуются semver tags, без `latest`; существующие release tags не перезаписываются. Production выбирает опубликованный version tag.
Compose topology принадлежит workspace, эксплуатационная последовательность — Compose topology принадлежит workspace, эксплуатационная последовательность —
[документация](https://git.personal.ksv741.ru/WealthLedger/docs), [документация](https://git.personal.ksv741.ru/WealthLedger/docs),
@@ -48,6 +51,25 @@ Compose topology принадлежит workspace, эксплуатационн
Проверка публикации требует настроенного registry/runner; локальный build Проверка публикации требует настроенного registry/runner; локальный build
не доказывает package permissions. не доказывает package permissions.
## Установка как приложение (PWA)
Production-сборка поддерживает установку WealthLedger в отдельное окно через
`vite-plugin-pwa`. Нужен HTTPS или localhost. В Chrome/Edge выберите «Установить
WealthLedger» в меню браузера или значок установки в адресной строке; на iPhone
и iPad — Safari → «Поделиться» → «На экран Домой». Доступность установки зависит
от браузера и ОС.
Service worker кеширует только статическую оболочку, включая страницы SPA.
Вход, финансовые данные и сохранение изменений требуют сети: API, токены и
ответы API не сохраняются в Cache Storage. Это не автономный финансовый
клиент. Новая версия загружается в фоне и применяется после закрытия всех
вкладок и окон WealthLedger и повторного открытия; открытые формы автоматически
не перезагружаются.
Локальная проверка: `nvm use --silent`, `npm run build`, `npm run preview`.
В DevTools → Application проверьте Manifest, Service Workers и Cache Storage.
В режиме `npm run dev` и в Storybook service worker не включается.
## Проверка ## Проверка
```bash ```bash
@@ -74,6 +96,42 @@ TypeScript остаётся на 5.9.3: `openapi-typescript@7.13.0` требуе
обновите `src/shared/api/spec/openapi.json` копированием backend OpenAPI обновите `src/shared/api/spec/openapi.json` копированием backend OpenAPI
document и затем выполните `npm run openapi:generate`. document и затем выполните `npm run openapi:generate`.
## SonarQube
Проект `wealthledger-frontend` использует настройки из
`sonar-project.properties`. Анализируются исходники `src`; тесты учитываются
отдельно, а Storybook fixtures, test helpers, generated API types и OpenAPI
snapshot исключены. `npm run test:coverage` (также входит в `npm run verify`)
создаёт `coverage/lcov.info` для импорта покрытия.
Для первого анализа установите SonarScanner CLI, совместимый с версией сервера,
и выполните из корня frontend:
```bash
nvm use --silent
npm ci
npm run test:coverage
# SONAR_TOKEN передайте через окружение; не сохраняйте токен в репозитории.
sonar-scanner
```
В Gitea откройте frontend → Settings → Actions → Secrets и добавьте
`SONAR_TOKEN` с токеном анализа проекта. Переименовывать основную ветку в
SonarQube не требуется; `sonar.branch.name` не задаётся.
Используется Community Edition 9.9.8: CI отправляет только
push в `develop`, после успешного `verify`, и ожидает результат Quality Gate.
PR и остальные ветки проходят обычные проверки без отправки в SonarQube.
Отрицательный Quality Gate или ошибка scanner завершает `verify` с ошибкой.
Runner должен поддерживать Docker actions и иметь HTTPS-доступ к
`https://sonarqube.personal.ksv741.ru`, GitHub и Docker Hub. Docker action
SonarSource закреплён на commit версии 2.3.0; scanner запускается отдельно от
Node 24, используемого для сборки. `tsconfig.sonar.json` содержит совместимые
со старым анализатором TS настройки; приложение проверяется штатным TypeScript
5.9 через `npm run verify`. После обновления сервера пересмотрите scanner и
возможность использовать основной tsconfig. Успешный локальный `verify` не
доказывает доступность сервера и успешность анализа в CI.
## UI-каталог Storybook ## UI-каталог Storybook
После `nvm use --silent` выполните `npm run dev:catalog`; статическая сборка — После `nvm use --silent` выполните `npm run dev:catalog`; статическая сборка —
+3 -1
View File
@@ -1,8 +1,10 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="ru">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<meta name="theme-color" content="#ffffff" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WealthLedger</title> <title>WealthLedger</title>
</head> </head>
+4573 -2
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "wealth-ledger-frontend", "name": "wealth-ledger-frontend",
"private": true, "private": true,
"version": "0.2.0", "version": "0.3.0",
"type": "module", "type": "module",
"engines": { "engines": {
"node": "24.21.0" "node": "24.21.0"
@@ -82,6 +82,7 @@
"storybook": "10.6.0", "storybook": "10.6.0",
"typescript": "5.9.3", "typescript": "5.9.3",
"vite": "8.3.0", "vite": "8.3.0",
"vite-plugin-pwa": "1.3.0",
"vitest": "5.0.0" "vitest": "5.0.0"
}, },
"allowScripts": { "allowScripts": {
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

+12
View File
@@ -0,0 +1,12 @@
sonar.projectKey=wealthledger-frontend
sonar.projectName=WealthLedger frontend
sonar.host.url=https://sonarqube.personal.ksv741.ru
sonar.sourceEncoding=UTF-8
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=src/**/*.test.ts,src/**/*.test.tsx
sonar.exclusions=src/**/*.test.ts,src/**/*.test.tsx,src/**/*.stories.tsx,src/test/**,src/shared/api/generated/**,src/shared/api/spec/**
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# SonarQube 9.9 embeds an older TypeScript analyzer than the application compiler.
sonar.typescript.tsconfigPaths=tsconfig.sonar.json
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"jsx": "react-jsx",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
},
"include": ["src"]
}
+46 -1
View File
@@ -2,10 +2,55 @@ import { fileURLToPath, URL } from "node:url";
import babel from "@rolldown/plugin-babel"; import babel from "@rolldown/plugin-babel";
import react, { reactCompilerPreset } from "@vitejs/plugin-react"; import react, { reactCompilerPreset } from "@vitejs/plugin-react";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react(), babel({ presets: [reactCompilerPreset()] })], plugins: [
react(),
babel({ presets: [reactCompilerPreset()] }),
VitePWA({
injectRegister: "script-defer",
// Let the waiting worker activate after all app windows close.
registerType: "prompt",
includeAssets: ["favicon.svg", "icons.svg", "apple-touch-icon.png"],
manifest: {
id: "/",
name: "WealthLedger",
short_name: "WealthLedger",
description: "Личные финансы и инвестиции",
lang: "ru",
start_url: "/",
scope: "/",
display: "standalone",
theme_color: "#ffffff",
background_color: "#ffffff",
icons: [
{ src: "/pwa-192x192.png", sizes: "192x192", type: "image/png" },
{ src: "/pwa-512x512.png", sizes: "512x512", type: "image/png" },
{
src: "/pwa-512x512.png",
sizes: "512x512",
type: "image/png",
purpose: "maskable",
},
],
},
workbox: {
globPatterns: ["**/*.{js,css,html,woff2}"],
// Only the static shell is cached; API requests always use the network.
navigateFallbackDenylist: [/^\/api(?:\/|$)/],
},
integration: {
configureOptions(config, options) {
// Storybook loads this Vite config but must not install an app worker.
options.disable = config.plugins.some((plugin) =>
plugin.name.startsWith("storybook:"),
);
},
},
}),
],
resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) } }, resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) } },
server: { server: {
proxy: { proxy: {
+1 -1
View File
@@ -21,7 +21,7 @@ export default defineConfig({
"src/**/*.test.{ts,tsx}", "src/**/*.test.{ts,tsx}",
"src/**/*.stories.tsx", "src/**/*.stories.tsx",
], ],
reporter: ["text", "html"], reporter: ["text", "html", "lcov"],
thresholds: { thresholds: {
statements: 82, statements: 82,
branches: 75, branches: 75,