ci setup
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
This commit is contained in:
186
.github/workflows/ci.yml
vendored
Normal file
186
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Job 1: Lint and Typecheck (Fast feedback)
|
||||||
|
lint-typecheck:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Run Typecheck
|
||||||
|
run: npm run typecheck
|
||||||
|
|
||||||
|
# Job 2: Unit and Integration Tests
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: lint-typecheck
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run Unit Tests
|
||||||
|
run: npm run test:unit
|
||||||
|
|
||||||
|
- name: Run Integration Tests
|
||||||
|
run: npm run test:integration
|
||||||
|
|
||||||
|
# Job 3: Contract Tests (API/Website compatibility)
|
||||||
|
contract-tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: lint-typecheck
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run API Contract Validation
|
||||||
|
run: npm run test:api:contracts
|
||||||
|
|
||||||
|
- name: Generate OpenAPI spec
|
||||||
|
run: npm run api:generate-spec
|
||||||
|
|
||||||
|
- name: Generate TypeScript types
|
||||||
|
run: npm run api:generate-types
|
||||||
|
|
||||||
|
- name: Run Contract Compatibility Check
|
||||||
|
run: npm run test:contract:compatibility
|
||||||
|
|
||||||
|
- name: Verify Website Type Checking
|
||||||
|
run: npm run website:type-check
|
||||||
|
|
||||||
|
- name: Upload generated types as artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: generated-types
|
||||||
|
path: apps/website/lib/types/generated/
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# Job 4: E2E Tests (Only on main/develop push, not on PRs)
|
||||||
|
e2e-tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint-typecheck, tests, contract-tests]
|
||||||
|
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run E2E Tests
|
||||||
|
run: npm run test:e2e
|
||||||
|
|
||||||
|
# Job 5: Comment PR with results (Only on PRs)
|
||||||
|
comment-pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint-typecheck, tests, contract-tests]
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Comment PR with results
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// Read any contract change reports
|
||||||
|
const reportPath = path.join(process.cwd(), 'contract-report.json');
|
||||||
|
if (fs.existsSync(reportPath)) {
|
||||||
|
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
|
||||||
|
|
||||||
|
const comment = `
|
||||||
|
## 🔍 CI Results
|
||||||
|
|
||||||
|
✅ **All checks passed!**
|
||||||
|
|
||||||
|
### Changes Summary:
|
||||||
|
- Total changes: ${report.totalChanges}
|
||||||
|
- Breaking changes: ${report.breakingChanges}
|
||||||
|
- Added: ${report.added}
|
||||||
|
- Removed: ${report.removed}
|
||||||
|
- Modified: ${report.modified}
|
||||||
|
|
||||||
|
Generated types are available as artifacts.
|
||||||
|
`;
|
||||||
|
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: comment
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Job 6: Commit generated types (Only on main branch push)
|
||||||
|
commit-types:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint-typecheck, tests, contract-tests]
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Generate and snapshot types
|
||||||
|
run: |
|
||||||
|
npm run api:generate-spec
|
||||||
|
npm run api:generate-types
|
||||||
|
|
||||||
|
- name: Commit generated types
|
||||||
|
run: |
|
||||||
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
git add apps/website/lib/types/generated/
|
||||||
|
git diff --staged --quiet || git commit -m "chore: update generated API types [skip ci]"
|
||||||
|
git push
|
||||||
110
.github/workflows/contract-testing.yml
vendored
110
.github/workflows/contract-testing.yml
vendored
@@ -1,110 +0,0 @@
|
|||||||
name: Contract Testing
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, develop]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, develop]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
contract-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run API contract validation
|
|
||||||
run: npm run test:api:contracts
|
|
||||||
|
|
||||||
- name: Generate OpenAPI spec
|
|
||||||
run: npm run api:generate-spec
|
|
||||||
|
|
||||||
- name: Generate TypeScript types
|
|
||||||
run: npm run api:generate-types
|
|
||||||
|
|
||||||
- name: Run contract compatibility check
|
|
||||||
run: npm run test:contract:compatibility
|
|
||||||
|
|
||||||
- name: Verify website type checking
|
|
||||||
run: npm run website:type-check
|
|
||||||
|
|
||||||
- name: Upload generated types as artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: generated-types
|
|
||||||
path: apps/website/lib/types/generated/
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: Comment PR with results
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
uses: actions/github-script@v6
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// Read any contract change reports
|
|
||||||
const reportPath = path.join(process.cwd(), 'contract-report.json');
|
|
||||||
if (fs.existsSync(reportPath)) {
|
|
||||||
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
|
|
||||||
|
|
||||||
const comment = `
|
|
||||||
## 🔍 Contract Testing Results
|
|
||||||
|
|
||||||
✅ **All contract tests passed!**
|
|
||||||
|
|
||||||
### Changes Summary:
|
|
||||||
- Total changes: ${report.totalChanges}
|
|
||||||
- Breaking changes: ${report.breakingChanges}
|
|
||||||
- Added: ${report.added}
|
|
||||||
- Removed: ${report.removed}
|
|
||||||
- Modified: ${report.modified}
|
|
||||||
|
|
||||||
Generated types are available as artifacts.
|
|
||||||
`;
|
|
||||||
|
|
||||||
github.rest.issues.createComment({
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
body: comment
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
contract-snapshot:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Generate and snapshot types
|
|
||||||
run: |
|
|
||||||
npm run api:generate-spec
|
|
||||||
npm run api:generate-types
|
|
||||||
|
|
||||||
- name: Commit generated types
|
|
||||||
run: |
|
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git add apps/website/lib/types/generated/
|
|
||||||
git diff --staged --quiet || git commit -m "chore: update generated API types [skip ci]"
|
|
||||||
git push
|
|
||||||
@@ -1 +1 @@
|
|||||||
npm test
|
npx lint-staged
|
||||||
24
README.md
24
README.md
@@ -64,12 +64,28 @@ Individual applications support hot reload and watch mode during development:
|
|||||||
GridPilot follows strict BDD (Behavior-Driven Development) with comprehensive test coverage.
|
GridPilot follows strict BDD (Behavior-Driven Development) with comprehensive test coverage.
|
||||||
|
|
||||||
### Local Verification Pipeline
|
### Local Verification Pipeline
|
||||||
Run this sequence before pushing to ensure correctness:
|
|
||||||
```bash
|
GridPilot uses **lint-staged** to automatically validate only changed files on commit:
|
||||||
npm run lint && npm run typecheck && npm run test:unit && npm run test:integration
|
|
||||||
```
|
- `eslint --fix` runs on changed JS/TS/TSX files
|
||||||
|
- `vitest related --run` runs tests related to changed files
|
||||||
|
- `prettier --write` formats JSON, MD, and YAML files
|
||||||
|
|
||||||
|
This ensures fast commits without running the full test suite.
|
||||||
|
|
||||||
|
### Pre-Push Hook
|
||||||
|
|
||||||
|
A **pre-push hook** runs the full verification pipeline before pushing to remote:
|
||||||
|
|
||||||
|
- `npm run lint` - Check for linting errors
|
||||||
|
- `npm run typecheck` - Verify TypeScript types
|
||||||
|
- `npm run test:unit` - Run unit tests
|
||||||
|
- `npm run test:integration` - Run integration tests
|
||||||
|
|
||||||
|
You can skip this with `git push --no-verify` if needed.
|
||||||
|
|
||||||
### Individual Commands
|
### Individual Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run all tests
|
# Run all tests
|
||||||
npm test
|
npm test
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -45,6 +45,7 @@
|
|||||||
"glob": "^13.0.0",
|
"glob": "^13.0.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
|
"lint-staged": "^15.2.10",
|
||||||
"openapi-typescript": "^7.4.3",
|
"openapi-typescript": "^7.4.3",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"puppeteer": "^24.31.0",
|
"puppeteer": "^24.31.0",
|
||||||
@@ -128,6 +129,7 @@
|
|||||||
"test:unit": "vitest run tests/unit",
|
"test:unit": "vitest run tests/unit",
|
||||||
"test:watch": "vitest watch",
|
"test:watch": "vitest watch",
|
||||||
"test:website:types": "vitest run --config vitest.website.config.ts apps/website/lib/types/contractConsumption.test.ts",
|
"test:website:types": "vitest run --config vitest.website.config.ts apps/website/lib/types/contractConsumption.test.ts",
|
||||||
|
"verify": "npm run lint && npm run typecheck && npm run test:unit && npm run test:integration",
|
||||||
"typecheck": "npm run typecheck:targets",
|
"typecheck": "npm run typecheck:targets",
|
||||||
"typecheck:grep": "npm run typescript",
|
"typecheck:grep": "npm run typescript",
|
||||||
"typecheck:root": "npx tsc --noEmit --project tsconfig.json",
|
"typecheck:root": "npx tsc --noEmit --project tsconfig.json",
|
||||||
@@ -139,6 +141,15 @@
|
|||||||
"website:start": "npm run start --workspace=@gridpilot/website",
|
"website:start": "npm run start --workspace=@gridpilot/website",
|
||||||
"website:type-check": "npm run type-check --workspace=@gridpilot/website"
|
"website:type-check": "npm run type-check --workspace=@gridpilot/website"
|
||||||
},
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,ts,tsx}": [
|
||||||
|
"eslint --fix",
|
||||||
|
"vitest related --run"
|
||||||
|
],
|
||||||
|
"*.{json,md,yml}": [
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
},
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"core/*",
|
"core/*",
|
||||||
|
|||||||
100
plans/ci-optimization.md
Normal file
100
plans/ci-optimization.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# CI/CD & Dev Experience Optimization Plan
|
||||||
|
|
||||||
|
## Current Situation
|
||||||
|
|
||||||
|
- **Husky `pre-commit`**: Runs `npm test` (Vitest) on every commit. This likely runs the entire test suite, which is slow and frustrating for developers.
|
||||||
|
- **Gitea Actions**: Currently only has `contract-testing.yml`.
|
||||||
|
- **Missing**: No automated linting or type-checking in CI, no tiered testing strategy.
|
||||||
|
|
||||||
|
## Proposed Strategy: The "Fast Feedback Loop"
|
||||||
|
|
||||||
|
We will implement a tiered approach to balance speed and safety.
|
||||||
|
|
||||||
|
### 1. Local Development (Husky + lint-staged)
|
||||||
|
|
||||||
|
**Goal**: Prevent obvious errors from entering the repo without slowing down the dev.
|
||||||
|
|
||||||
|
- **Trigger**: `pre-commit`
|
||||||
|
- **Action**: Only run on **staged files**.
|
||||||
|
- **Tasks**:
|
||||||
|
- `eslint --fix`
|
||||||
|
- `prettier --write`
|
||||||
|
- `vitest related` (only run tests related to changed files)
|
||||||
|
|
||||||
|
### 2. Pull Request (Gitea Actions)
|
||||||
|
|
||||||
|
**Goal**: Ensure the branch is stable and doesn't break the build or other modules.
|
||||||
|
|
||||||
|
- **Trigger**: PR creation and updates.
|
||||||
|
- **Tasks**:
|
||||||
|
- Full `lint`
|
||||||
|
- Full `typecheck` (crucial for monorepo integrity)
|
||||||
|
- Full `unit tests`
|
||||||
|
- `integration tests`
|
||||||
|
- `contract tests`
|
||||||
|
|
||||||
|
### 3. Merge to Main / Release (Gitea Actions)
|
||||||
|
|
||||||
|
**Goal**: Final verification before deployment.
|
||||||
|
|
||||||
|
- **Trigger**: Push to `main` or `develop`.
|
||||||
|
- **Tasks**:
|
||||||
|
- Everything from PR stage.
|
||||||
|
- `e2e tests` (Playwright) - these are the slowest and most expensive.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
### Step 1: Install and Configure `lint-staged`
|
||||||
|
|
||||||
|
We need to add `lint-staged` to [`package.json`](package.json) and update the Husky hook.
|
||||||
|
|
||||||
|
### Step 2: Optimize Husky Hook
|
||||||
|
|
||||||
|
Update [`.husky/pre-commit`](.husky/pre-commit) to run `npx lint-staged` instead of `npm test`.
|
||||||
|
|
||||||
|
### Step 3: Create Comprehensive CI Workflow
|
||||||
|
|
||||||
|
Create `.github/workflows/ci.yml` (Gitea Actions compatible) to handle the heavy lifting.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Diagram
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[Developer Commits] --> B{Husky pre-commit}
|
||||||
|
B -->|lint-staged| C[Lint/Format Changed Files]
|
||||||
|
C --> D[Run Related Tests]
|
||||||
|
D --> E[Commit Success]
|
||||||
|
|
||||||
|
E --> F[Push to PR]
|
||||||
|
F --> G{Gitea CI PR Job}
|
||||||
|
G --> H[Full Lint & Typecheck]
|
||||||
|
G --> I[Full Unit & Integration Tests]
|
||||||
|
G --> J[Contract Tests]
|
||||||
|
|
||||||
|
J --> K{Merge to Main}
|
||||||
|
K --> L{Gitea CI Main Job}
|
||||||
|
L --> M[All PR Checks]
|
||||||
|
L --> N[Full E2E Tests]
|
||||||
|
N --> O[Deploy/Release]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Proposed `lint-staged` Configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"*.{js,ts,tsx}": ["eslint --fix", "vitest related --run"],
|
||||||
|
"*.{json,md,yml}": ["prettier --write"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions for the User
|
||||||
|
|
||||||
|
1. Do you want to include `typecheck` in the `pre-commit` hook? (Note: `tsc` doesn't support linting only changed files easily, so it usually checks the whole project, which might be slow).
|
||||||
|
2. Should we run `integration tests` on every PR, or only on merge to `main`?
|
||||||
|
3. Are there specific directories that should be excluded from this automated flow?
|
||||||
Reference in New Issue
Block a user