diff --git a/.gitea/workflows/commits.yml b/.gitea/workflows/commits.yml deleted file mode 100644 index 2372d2c..0000000 --- a/.gitea/workflows/commits.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Conventional commits - -on: - pull_request: - types: [opened, synchronize, reopened, edited] - -jobs: - commits: - runs-on: ubuntu-latest - steps: - - uses: https://github.com/actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - uses: https://github.com/actions/setup-node@v4 - with: - node-version-file: .nvmrc - - run: npm ci --ignore-scripts - - name: Check PR title and commits - env: - PR_TITLE: ${{ github.event.pull_request.title }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: | - printf '%s\n' "$PR_TITLE" | npm run commitlint -- --strict - npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA" diff --git a/.gitea/workflows/security.yml b/.gitea/workflows/security.yml deleted file mode 100644 index aab00cb..0000000 --- a/.gitea/workflows/security.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Frontend security - -on: - push: - branches: - - '**' - pull_request: - schedule: - - cron: '17 5 * * *' - -jobs: - security: - 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 - - name: Scan history with Gitleaks 8.30.1 - run: | - curl --fail --location --silent --show-error https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz -o /tmp/gitleaks.tar.gz - echo '551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb /tmp/gitleaks.tar.gz' | sha256sum --check - mkdir -p /tmp/gitleaks-bin - tar -xzf /tmp/gitleaks.tar.gz -C /tmp/gitleaks-bin gitleaks - /tmp/gitleaks-bin/gitleaks git --log-opts=--all --redact=100 --no-banner - - uses: https://github.com/actions/setup-node@v4 - with: - node-version-file: .nvmrc - - name: Verify pre-commit secret blocking and redaction - run: PATH=/tmp/gitleaks-bin:$PATH node --test scripts/test-pre-commit.mjs - - name: Audit runtime and development dependencies - run: npm audit --include=dev --audit-level=low diff --git a/.gitea/workflows/verify.yml b/.gitea/workflows/verify.yml index 8664042..de41d41 100644 --- a/.gitea/workflows/verify.yml +++ b/.gitea/workflows/verify.yml @@ -2,12 +2,74 @@ name: Frontend verify on: push: - branches: - - '**' + branches: [develop, main] pull_request: + types: [opened, synchronize, reopened, edited] + schedule: + - cron: '17 5 * * *' + +# Gitea >= 1.26. A new revision supersedes only the same PR/branch/event. +concurrency: + group: frontend-verify-${{ gitea.event_name }}-${{ gitea.event.pull_request.number || gitea.ref }} + cancel-in-progress: true jobs: + commits: + if: gitea.event_name == 'pull_request' + timeout-minutes: 15 + runs-on: ubuntu-latest + steps: + - uses: https://github.com/actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - uses: https://github.com/actions/setup-node@v4 + with: + node-version-file: .nvmrc + - run: npm ci --ignore-scripts + - name: Check PR title and commits + env: + PR_TITLE: ${{ github.event.pull_request.title }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: | + printf '%s\n' "$PR_TITLE" | npm run commitlint -- --strict + npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA" + + security: + needs: commits + if: >- + !cancelled() && + (needs.commits.result == 'success' || needs.commits.result == 'skipped') + timeout-minutes: 15 + 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 + - name: Scan history with Gitleaks 8.30.1 + run: | + curl --fail --location --silent --show-error https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz -o /tmp/gitleaks.tar.gz + echo '551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb /tmp/gitleaks.tar.gz' | sha256sum --check + mkdir -p /tmp/gitleaks-bin + tar -xzf /tmp/gitleaks.tar.gz -C /tmp/gitleaks-bin gitleaks + /tmp/gitleaks-bin/gitleaks git --log-opts=--all --redact=100 --no-banner + - uses: https://github.com/actions/setup-node@v4 + with: + node-version-file: .nvmrc + - name: Verify pre-commit secret blocking and redaction + run: PATH=/tmp/gitleaks-bin:$PATH node --test scripts/test-pre-commit.mjs + - name: Audit runtime and development dependencies + run: npm audit --include=dev --audit-level=low + verify: + needs: [commits, security] + if: >- + !cancelled() && needs.security.result == 'success' && + gitea.event_name != 'schedule' + timeout-minutes: 45 runs-on: ubuntu-latest steps: - uses: https://github.com/actions/checkout@v4 diff --git a/README.md b/README.md index 0097ab0..ddaee74 100644 --- a/README.md +++ b/README.md @@ -88,14 +88,30 @@ Chromium при ширинах 375 и 1280 px. Browser project не исполь и его заглушки layout API. Только браузерная проверка: `npm run test:run -- --project='browser-*'`. После обновления Playwright повторите установку Chromium; CI устанавливает его с `--with-deps` для Linux. -Отдельный CI workflow `Frontend security` на push, pull request и ежедневно -проверяет полную доступную историю Gitleaks 8.30.1 и выполняет +Единый `.gitea/workflows/verify.yml` запускает `commits → security → verify` +последовательно на PR; на push в `develop`/`main` — `security → verify`. +Рабочие ветки проверяются после открытия PR, без дублирующего push-запуска. +Изменение заголовка PR тоже повторяет проверки Conventional Commits. +Новый запуск отменяет устаревший для того же PR/ветки и типа события +(требуется Gitea 1.26+). Ежедневно в 05:17 UTC выполняется только `security`. +Job `security` проверяет полную доступную историю Gitleaks 8.30.1 и выполняет `npm audit --include=dev --audit-level=low`. Любой advisory блокирует security job; исключений frontend нет. Локально можно выполнить те же команды: `gitleaks git --log-opts=--all --redact=100 --no-banner` и `npm audit --include=dev --audit-level=low`. Audit требует доступа к npm registry; проверка секретов выполняется локально и не выводит их значения. +Имена jobs `commits`, `security`, `verify` сохранены, но Gitea включает имя +workflow в статус. При внедрении администратор должен заменить required checks +для защищённых веток на `Frontend verify / commits (pull_request)`, +`Frontend verify / security (pull_request)` и +`Frontend verify / verify (pull_request)`, удалив старые имена и push-статусы, +если они требовались. Все три PR-проверки должны оставаться обязательными. +Публикация образов по тегам остаётся в `image.yml`. +Последовательность jobs ограничивает один запуск; для ограничения нагрузки всего сервера настройте +`runner.capacity: 1` у общего runner и учтите остальные зарегистрированные +runners. Конфигурация runner управляется вне этого репозитория. + TypeScript остаётся на 5.9.3: `openapi-typescript@7.13.0` требует peer `^5.x`. Обновление до TypeScript 7 из Renovate dashboard откладывается до совместимого релиза генератора; `--force`/`--legacy-peer-deps` для обхода этого ограничения