Skip to content

Frontend CI/CD

The granit-front pipeline runs on pull requests, develop, main, and semantic tags (v*.*.*).

flowchart LR
    Q[quality] --> S[security] --> T[test] --> A[analysis]
StageJobsDescription
qualitylint, typecheckESLint (0 warnings) + TypeScript strict
securitygitleaks, codeql, trivySecret scanning, SAST, vulnerability scanning
testtestVitest with v8 coverage
analysisaudit:npm, sonarqubeDependency audit + SonarQube
ParameterValue
Imagenode:24-bookworm-slim
Package managerpnpm 10 (via corepack)
Cache.pnpm-store/ (key: pnpm-lock.yaml)
Husky hooksDisabled in CI (HUSKY=0)
Terminal window
pnpm lint

ESLint with --max-warnings 0. Zero warnings tolerated.

Notable rules:

  • no-console as error (except in @granit/logger)
  • @typescript-eslint/consistent-type-importsimport type required
  • import/order — imports sorted by group
Terminal window
pnpm tsc # pnpm -r exec -- tsc --noEmit

TypeScript strict on all packages: no implicit any, no unused variables, no unused parameters.

Secret detection — Gitleaks via GitHub Actions. A detected secret blocks the pipeline (continue-on-error: false).

SAST — Static analysis via CodeQL. CodeQL is blocking (continue-on-error: false).

Vulnerability scanning — Trivy scans for known vulnerabilities. Trivy is blocking (continue-on-error: false).

Terminal window
pnpm test:coverage

Vitest single-run with coverage. Generated artifacts:

ArtifactRetentionUsage
coverage/cobertura-coverage.xml1 weekPR coverage widget
coverage/ (HTML + lcov)1 weekLocal browsing + SonarQube
Terminal window
pnpm audit --audit-level moderate

Checks known vulnerabilities in dependencies (moderate and above). continue-on-error: true — informational, does not block the pipeline.

Conditional — runs only when SONAR_HOST_URL and SONAR_TOKEN are set.

  • Sources: packages/
  • Coverage: coverage/lcov.info
  • Exclusions: **/*.test.ts, **/*.test.tsx, **/*.d.ts
  • continue-on-error: true
gitgraph
    commit id: "main"
    branch develop
    commit id: "feat: logger"
    branch feature/auth
    commit id: "feat: auth init"
    commit id: "feat: auth context"
    checkout develop
    merge feature/auth
    branch release/1.0
    commit id: "chore: version"
    checkout main
    merge release/1.0 tag: "v1.0.0"
    checkout develop
    merge release/1.0
BranchRole
mainProduction — direct push forbidden
developContinuous integration
feature/*Feature development
release/*Release preparation
hotfix/*Urgent fixes

Local Git hooks (via Husky) run automatically:

HookCommand
pre-commitpnpm lint && pnpm tsc
commit-msgpnpm exec commitlint --edit

Commit messages follow Conventional Commits: feat:, fix:, docs:, chore:, refactor:, test:.

Releases follow semantic versioning (vMAJOR.MINOR.PATCH):

  1. Create a release/X.Y branch from develop
  2. Verify the pipeline passes (lint + tsc + tests + security)
  3. Merge into main via PR (1 approval minimum)
  4. Tag on main: vX.Y.Z
  5. Merge main back into develop