diff --git a/.gitea/workflows/image.yml b/.gitea/workflows/image.yml index 4e48340..964a283 100644 --- a/.gitea/workflows/image.yml +++ b/.gitea/workflows/image.yml @@ -12,7 +12,7 @@ jobs: publish: runs-on: ubuntu-latest env: - IMAGE: git.personal.ksv741.ru/wealthledger/frontend + IMAGE: nexus.ksv741.keenetic.pro/wealthledger/frontend RELEASE_TAG: ${{ gitea.ref_name }} REVISION: ${{ gitea.sha }} DOCKER_CONFIG: ${{ runner.temp }}/wealthledger-frontend-docker @@ -33,14 +33,14 @@ jobs: - run: npm run verify env: KNIP_DISABLE_RAW_TRANSFER: '1' - - name: Login with dedicated package writer + - name: Login with dedicated Nexus writer env: - REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} - REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + REGISTRY_USERNAME: ${{ secrets.NEXUS_USERNAME }} + REGISTRY_TOKEN: ${{ secrets.NEXUS_PASSWORD }} run: | test -n "$REGISTRY_USERNAME" && test -n "$REGISTRY_TOKEN" 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.ksv741.keenetic.pro --username "$REGISTRY_USERNAME" --password-stdin - name: Publish immutable release tag run: | VERSION="${RELEASE_TAG#v}" diff --git a/.gitea/workflows/verify.yml b/.gitea/workflows/verify.yml index 5e4898f..bd7f96f 100644 --- a/.gitea/workflows/verify.yml +++ b/.gitea/workflows/verify.yml @@ -11,6 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: https://github.com/actions/checkout@v4 + with: + fetch-depth: 0 - name: Record checked revision run: git rev-parse HEAD - uses: https://github.com/actions/setup-node@v4 @@ -24,3 +26,11 @@ jobs: env: # OXC raw transfer allocates a ~6 GiB buffer; use the standard parser in CI. 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 diff --git a/.gitignore b/.gitignore index c2a0011..17ca640 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ dist storybook-static dist-ssr coverage +.scannerwork *.local # Local runtime configuration diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6ca60..a53c111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [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) ### Features diff --git a/README.md b/README.md index d5f4d81..50e25a8 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,13 @@ docker build --target production -t wealthledger-frontend:production . Gitea `image.yml` запускается на защищённом release tag `vX.Y.Z`, проверяет package/lock version и canonical gates. Runner `ubuntu-latest` должен иметь -Docker/buildx. Dedicated package writer задаётся Actions secrets -`REGISTRY_USERNAME`/`REGISTRY_TOKEN`; server использует отдельную read-only -identity. Публикуются semver tags, без `latest`; существующие -release tags не перезаписываются. Production выбирает опубликованный version tag. +Docker/buildx. Образы хранятся в Nexus: +`nexus.ksv741.keenetic.pro/wealthledger/frontend`. Пользователь `wealthledger-ci` +задаётся Actions secrets `NEXUS_USERNAME`/`NEXUS_PASSWORD`; эта же учётная +запись используется сервером для загрузки образов. Docker endpoint и token realm должны использовать +HTTPS; в `docker-hosted` включается запрет redeploy. Прежние Gitea secrets +сохраняются на время перехода и не передаются в Nexus. +Публикуются semver tags, без `latest`; существующие release tags не перезаписываются. Production выбирает опубликованный version tag. Compose topology принадлежит workspace, эксплуатационная последовательность — [документация](https://git.personal.ksv741.ru/WealthLedger/docs), @@ -74,6 +77,42 @@ TypeScript остаётся на 5.9.3: `openapi-typescript@7.13.0` требуе обновите `src/shared/api/spec/openapi.json` копированием backend OpenAPI 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.ksv741.keenetic.pro`, 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 После `nvm use --silent` выполните `npm run dev:catalog`; статическая сборка — diff --git a/package-lock.json b/package-lock.json index 297c33a..ca7b1d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wealth-ledger-frontend", - "version": "0.2.0", + "version": "0.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wealth-ledger-frontend", - "version": "0.2.0", + "version": "0.2.1", "dependencies": { "@hookform/resolvers": "5.9.1", "@mantine/charts": "9.6.1", diff --git a/package.json b/package.json index c5f7caf..6119e6b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wealth-ledger-frontend", "private": true, - "version": "0.2.0", + "version": "0.2.1", "type": "module", "engines": { "node": "24.21.0" diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..e9631e6 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,12 @@ +sonar.projectKey=wealthledger-frontend +sonar.projectName=WealthLedger frontend +sonar.host.url=https://sonarqube.ksv741.keenetic.pro +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 diff --git a/tsconfig.sonar.json b/tsconfig.sonar.json new file mode 100644 index 0000000..7d071c3 --- /dev/null +++ b/tsconfig.sonar.json @@ -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"] +} diff --git a/vitest.config.ts b/vitest.config.ts index 886917c..611525c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -21,7 +21,7 @@ export default defineConfig({ "src/**/*.test.{ts,tsx}", "src/**/*.stories.tsx", ], - reporter: ["text", "html"], + reporter: ["text", "html", "lcov"], thresholds: { statements: 82, branches: 75,