feat: rename rails/ to tools/ and add service tool suites (#4)
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #4.
This commit is contained in:
174
tools/quality/docs/CI-SETUP.md
Normal file
174
tools/quality/docs/CI-SETUP.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# CI/CD Configuration Guide
|
||||
|
||||
Configure Woodpecker CI, GitHub Actions, or GitLab CI for quality enforcement.
|
||||
|
||||
## Woodpecker CI
|
||||
|
||||
Quality Rails includes `.woodpecker.yml` template.
|
||||
|
||||
### Pipeline Stages
|
||||
|
||||
1. **Install** - Dependencies
|
||||
2. **Security Audit** - npm audit for CVEs
|
||||
3. **Lint** - ESLint checks
|
||||
4. **Type Check** - TypeScript compilation
|
||||
5. **Test** - Jest with coverage thresholds
|
||||
6. **Build** - Production build
|
||||
|
||||
### Configuration
|
||||
|
||||
No additional configuration needed. Push to repository and Woodpecker runs automatically.
|
||||
|
||||
### Blocking Merges
|
||||
|
||||
Configure Woodpecker to block merges on pipeline failure:
|
||||
1. Repository Settings → Protected Branches
|
||||
2. Require Woodpecker pipeline to pass
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
Copy from `templates/typescript-node/.github/workflows/quality.yml`:
|
||||
|
||||
```yaml
|
||||
name: Quality Enforcement
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm audit --audit-level=high
|
||||
- run: npm run lint
|
||||
- run: npm run type-check
|
||||
- run: npm run test -- --coverage
|
||||
- run: npm run build
|
||||
```
|
||||
|
||||
### Blocking Merges
|
||||
|
||||
1. Repository Settings → Branches → Branch protection rules
|
||||
2. Require status checks to pass: `quality`
|
||||
|
||||
## GitLab CI
|
||||
|
||||
Copy from `templates/typescript-node/.gitlab-ci.yml`:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- install
|
||||
- audit
|
||||
- quality
|
||||
- build
|
||||
|
||||
install:
|
||||
stage: install
|
||||
script:
|
||||
- npm ci
|
||||
|
||||
audit:
|
||||
stage: audit
|
||||
script:
|
||||
- npm audit --audit-level=high
|
||||
|
||||
lint:
|
||||
stage: quality
|
||||
script:
|
||||
- npm run lint
|
||||
|
||||
typecheck:
|
||||
stage: quality
|
||||
script:
|
||||
- npm run type-check
|
||||
|
||||
test:
|
||||
stage: quality
|
||||
script:
|
||||
- npm run test -- --coverage
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- npm run build
|
||||
```
|
||||
|
||||
## Coverage Enforcement
|
||||
|
||||
Configure Jest coverage thresholds in `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"jest": {
|
||||
"coverageThreshold": {
|
||||
"global": {
|
||||
"branches": 80,
|
||||
"functions": 80,
|
||||
"lines": 80,
|
||||
"statements": 80
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
CI will fail if coverage drops below threshold.
|
||||
|
||||
## Security Scanning
|
||||
|
||||
### npm audit
|
||||
|
||||
Runs automatically in CI. Adjust sensitivity:
|
||||
|
||||
```bash
|
||||
npm audit --audit-level=moderate # Block moderate+
|
||||
npm audit --audit-level=high # Block high+critical only
|
||||
npm audit --audit-level=critical # Block critical only
|
||||
```
|
||||
|
||||
### Snyk Integration
|
||||
|
||||
Add to CI for additional security:
|
||||
|
||||
```yaml
|
||||
- run: npx snyk test
|
||||
```
|
||||
|
||||
Requires `SNYK_TOKEN` environment variable.
|
||||
|
||||
## Notification Setup
|
||||
|
||||
### Woodpecker
|
||||
|
||||
Configure in Woodpecker UI:
|
||||
- Slack/Discord webhooks
|
||||
- Email notifications
|
||||
- Status badges
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
Add notification step:
|
||||
|
||||
```yaml
|
||||
- name: Notify on failure
|
||||
if: failure()
|
||||
run: |
|
||||
curl -X POST $WEBHOOK_URL -d "Build failed"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Pipeline fails but pre-commit passed:**
|
||||
- CI runs all packages, pre-commit only checks changed files
|
||||
- Fix issues in all packages, not just changed files
|
||||
|
||||
**npm audit blocks on low-severity:**
|
||||
- Adjust `--audit-level` to `moderate` or `high`
|
||||
|
||||
**Coverage threshold too strict:**
|
||||
- Lower thresholds in package.json
|
||||
- Add coverage exceptions for specific files
|
||||
164
tools/quality/docs/TYPESCRIPT-SETUP.md
Normal file
164
tools/quality/docs/TYPESCRIPT-SETUP.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# TypeScript Project Setup Guide
|
||||
|
||||
Step-by-step guide to add Quality Rails to a TypeScript project.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 18+ and npm/pnpm
|
||||
- Git repository initialized
|
||||
- TypeScript project (or create with `npm init` + `tsc --init`)
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Clone Quality Rails
|
||||
|
||||
```bash
|
||||
git clone git@git.mosaicstack.dev:mosaic/quality-rails.git
|
||||
```
|
||||
|
||||
### 2. Run Installation Script
|
||||
|
||||
```bash
|
||||
# From your project directory
|
||||
../quality-rails/scripts/install.sh --template typescript-node --target .
|
||||
```
|
||||
|
||||
This copies:
|
||||
- `.husky/pre-commit` - Git hooks
|
||||
- `.lintstagedrc.js` - Pre-commit checks
|
||||
- `.eslintrc.js` - Strict ESLint rules
|
||||
- `tsconfig.json` - TypeScript strict mode
|
||||
- `.woodpecker.yml` - CI pipeline
|
||||
|
||||
### 3. Install Dependencies
|
||||
|
||||
Add to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"lint": "eslint 'src/**/*.{ts,tsx}' --max-warnings=0",
|
||||
"type-check": "tsc --noEmit",
|
||||
"test": "jest",
|
||||
"build": "tsc",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-security": "^3.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.0.0",
|
||||
"lint-staged": "^16.2.7",
|
||||
"prettier": "^3.0.0",
|
||||
"typescript": "^5.6.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run:
|
||||
```bash
|
||||
npm install
|
||||
npx husky install
|
||||
```
|
||||
|
||||
### 4. Verify Enforcement
|
||||
|
||||
```bash
|
||||
../quality-rails/scripts/verify.sh
|
||||
```
|
||||
|
||||
Should output:
|
||||
```
|
||||
✅ PASS: Type errors blocked
|
||||
✅ PASS: 'any' types blocked
|
||||
✅ PASS: Lint errors blocked
|
||||
```
|
||||
|
||||
## What Gets Enforced
|
||||
|
||||
### TypeScript Strict Mode
|
||||
|
||||
All strict checks enabled in `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictBindCallApply": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ESLint Rules
|
||||
|
||||
Key rules in `.eslintrc.js`:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'@typescript-eslint/no-explicit-any': 'error', // Block 'any' types
|
||||
'@typescript-eslint/explicit-function-return-type': 'warn', // Require return types
|
||||
'@typescript-eslint/no-floating-promises': 'error', // Catch unhandled promises
|
||||
'@typescript-eslint/no-misused-promises': 'error', // Prevent promise misuse
|
||||
}
|
||||
```
|
||||
|
||||
### Pre-Commit Checks
|
||||
|
||||
On every `git commit`, runs:
|
||||
1. ESLint with --max-warnings=0
|
||||
2. TypeScript type check
|
||||
3. Prettier formatting
|
||||
4. Secret scanning (if git-secrets installed)
|
||||
|
||||
If any fail → **commit blocked**.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "husky - pre-commit hook exited with code 1"
|
||||
|
||||
This means pre-commit checks failed. Read the error output:
|
||||
|
||||
```
|
||||
src/example.ts:5:14 - error TS2322: Type 'number' is not assignable to type 'string'
|
||||
```
|
||||
|
||||
Fix the error and commit again.
|
||||
|
||||
### "Cannot find module '@typescript-eslint/parser'"
|
||||
|
||||
Dependencies not installed:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Pre-commit hooks not running
|
||||
|
||||
Husky not initialized:
|
||||
```bash
|
||||
npx husky install
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
See [CUSTOMIZATION.md](./CUSTOMIZATION.md) for adjusting strictness levels.
|
||||
|
||||
## CI/CD Setup
|
||||
|
||||
See [CI-SETUP.md](./CI-SETUP.md) for Woodpecker/GitHub Actions configuration.
|
||||
Reference in New Issue
Block a user