name: Frontend verify on: push: branches: [develop, main] pull_request: types: [opened, synchronize, reopened] 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 if [[ "$PR_TITLE" =~ ^chore\(release\):\ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then npm run commitlint -- --strict --from "$HEAD_SHA^" --to "$HEAD_SHA" else npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA" fi 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 with: fetch-depth: 0 - name: Record checked revision run: git rev-parse HEAD - uses: https://github.com/actions/setup-node@v4 with: node-version-file: .nvmrc - run: npm ci env: HUSKY: '0' - name: Install Chromium and system dependencies run: npx --no-install playwright install --with-deps chromium - name: Run all frontend gates run: npm run verify 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