mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
feat: add new icon components including Envelope, ChatCircle, HardDrives, WarningCircle, CheckCircle, XCircle, TrendUp, ShieldWarning, LockKey, Crown, Sparkle, BookOpen, Tree, Broom, Export, UploadSimple, Funnel, FunnelSimple, MapTrifold, PushPinSimple, Buildings, GithubLogo, and GoogleLogo
This commit is contained in:
402
.github/COPILOT_ANALYSIS.md
vendored
402
.github/COPILOT_ANALYSIS.md
vendored
@@ -1,201 +1,201 @@
|
||||
# Copilot Instructions Update Summary
|
||||
|
||||
## Generated: December 25, 2025
|
||||
|
||||
### File Updated
|
||||
`.github/copilot-instructions.md` - **~160 lines** of concise, actionable guidance for AI coding agents
|
||||
|
||||
### Analysis Approach
|
||||
|
||||
1. **Examined existing instructions**
|
||||
- `dbal/docs/AGENTS.md` (605 lines) - DBAL-specific agent development guide
|
||||
- `.github/copilot-instructions.md` (existing) - Original generic guidance
|
||||
|
||||
2. **Analyzed codebase patterns** through:
|
||||
- Database schema (`prisma/schema.prisma`) - Multi-tenant data model
|
||||
- Core libs: `database.ts`, `package-loader.ts`, `declarative-component-renderer.ts`
|
||||
- Test patterns: `schema-utils.test.ts` (441 lines, 63 parameterized tests)
|
||||
- Package system: `/packages/*/seed/` structure across 8 packages
|
||||
- Component patterns: `RenderComponent.tsx` (generic declarative renderer)
|
||||
- Security: `password-utils.ts`, `secure-db-layer.ts`, `sandboxed-lua-engine.ts`
|
||||
|
||||
3. **Discovered critical knowledge gaps** in original instructions:
|
||||
- No mention of DBAL architecture (critical for full codebase understanding)
|
||||
- Missing package loader workflow (`initializePackageSystem()`)
|
||||
- No guidance on parameterized testing pattern (100+ tests using `it.each()`)
|
||||
- Incomplete database pattern description
|
||||
- No mention of Fengari Lua integration specifics
|
||||
|
||||
## What's New in Updated Instructions
|
||||
|
||||
### 1. Architecture Overview Section
|
||||
**Why it matters**: Developers need to understand the 5-level permission system, DBAL's dual implementation (TS + C++), and multi-tenancy from day one.
|
||||
|
||||
```
|
||||
- 5-Level Permission System: Public → User → Admin → God → Supergod
|
||||
- DBAL: TypeScript SDK + C++ daemon with YAML contracts for language-agnostic APIs
|
||||
- Declarative Components: RenderComponent pattern for JSON-driven UIs
|
||||
- Package System: `/packages/{name}/seed/` self-contained modules
|
||||
- Multi-Tenancy: All queries filter by tenantId
|
||||
```
|
||||
|
||||
### 2. Critical Patterns (5 core patterns)
|
||||
**Why this section**: Previous instructions mixed patterns with conventions. These are the "must understand" patterns:
|
||||
|
||||
1. **API-First DBAL** - YAML → Types → TypeScript adapter → C++ adapter → Conformance tests
|
||||
2. **Generic Components** - `RenderComponent` with config instead of hardcoded TSX
|
||||
3. **Package Seeds** - `packages/{name}/seed/metadata.json` auto-loaded by `initializePackageSystem()`
|
||||
4. **Database Helpers** - Always use `Database.*` methods, never raw Prisma
|
||||
5. **Lua Sandboxing** - Scripts isolated, no `os`/`io`/`require` access
|
||||
|
||||
### 3. Test Patterns with Real Examples
|
||||
**Why new**: Original instructions said "write tests" without showing the actual pattern used in this codebase.
|
||||
|
||||
```typescript
|
||||
// Actual pattern from schema-utils.test.ts
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
```
|
||||
|
||||
### 4. DBAL-Specific Guidance
|
||||
**Why critical**: DBAL is 20% of the codebase. Agents need to know:
|
||||
- TypeScript impl = fast iteration
|
||||
- C++ impl = production security
|
||||
- Conformance tests = guarantee parity
|
||||
- YAML schemas = source of truth
|
||||
|
||||
### 5. Multi-Tenant Safety Patterns
|
||||
**Why essential**: Multi-tenancy bugs are catastrophic. Explicit examples:
|
||||
|
||||
```typescript
|
||||
// ❌ Never - exposes all tenants' data
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Always - isolates by tenant
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
## Discoverable Patterns Documented
|
||||
|
||||
### 1. Package Loading Workflow
|
||||
```
|
||||
initializePackageSystem()
|
||||
↓
|
||||
buildPackageRegistry() [reads /packages directory]
|
||||
↓
|
||||
exportAllPackagesForSeed() [extracts components, scripts, metadata]
|
||||
↓
|
||||
loadPackageComponents() [registers with declarative renderer]
|
||||
↓
|
||||
Package data available at runtime
|
||||
```
|
||||
|
||||
### 2. Seed Data Initialization
|
||||
- `src/seed-data/` directory with modular files: `users.ts`, `components.ts`, `workflows.ts`, `scripts.ts`, `pages.ts`, `packages.ts`
|
||||
- Each module has `initialize*()` async function
|
||||
- Called from `initializeAllSeedData()` in `App.tsx` on startup
|
||||
|
||||
### 3. Test Coverage Enforcement
|
||||
- Auto-generated coverage report: `FUNCTION_TEST_COVERAGE.md`
|
||||
- Check function coverage: `npm run test:check-functions`
|
||||
- Coverage report: `npm run test:coverage:report`
|
||||
- Parameterized test pattern reduces code duplication by ~60%
|
||||
|
||||
### 4. Component Size Limits
|
||||
- Hard limit: 150 LOC (except `RenderComponent.tsx` which uses recursive pattern)
|
||||
- Enforced by code review and linting patterns
|
||||
- Solution: Use generic `RenderComponent` + JSON config
|
||||
|
||||
## Connecting to Key Files
|
||||
|
||||
Instructions now reference:
|
||||
|
||||
| File | Purpose | Why Referenced |
|
||||
|------|---------|-----------------|
|
||||
| `dbal/docs/AGENTS.md` | DBAL development guide | Critical for DBAL changes |
|
||||
| `src/lib/database.ts` | Database operations | 1200+ LOC utility wrapper, required for all DB access |
|
||||
| `src/components/RenderComponent.tsx` | Generic renderer | 221 LOC example of declarative UI pattern |
|
||||
| `src/lib/schema-utils.test.ts` | Test examples | 63 tests showing parameterized pattern |
|
||||
| `docs/architecture/5-level-system.md` | Permission model | Understanding multi-level access control |
|
||||
| `docs/architecture/packages.md` | Package system | Understanding modular package structure |
|
||||
| `prisma/schema.prisma` | Data model | Multi-tenant schema structure |
|
||||
|
||||
## Sections Retained from Original
|
||||
|
||||
✅ Component size limits (< 150 LOC)
|
||||
✅ Functional components with hooks
|
||||
✅ `@/` absolute paths with shadcn/ui
|
||||
✅ Tailwind-only styling
|
||||
✅ SHA-512 password hashing
|
||||
✅ Sandbox Lua execution
|
||||
✅ Database-driven configuration preference
|
||||
|
||||
## New Guidance Not in Original
|
||||
|
||||
✅ DBAL dual-implementation architecture
|
||||
✅ Parameterized test patterns with examples
|
||||
✅ Package loader workflow
|
||||
✅ Multi-tenant query patterns (explicit examples)
|
||||
✅ Conformance test process for DBAL
|
||||
✅ API-First development (YAML → Types → Impl)
|
||||
✅ Fengari Lua integration specifics
|
||||
✅ Common mistakes with fixes
|
||||
|
||||
## How Agents Should Use This
|
||||
|
||||
1. **On startup**: Read "Architecture Overview" to understand the 4 pillars
|
||||
2. **Before implementation**: Check "Critical Patterns" (5 patterns) + relevant section
|
||||
3. **During code review**: Run through "Common Mistakes" checklist
|
||||
4. **When fixing bugs**: Check "DBAL-Specific Guidance" if involving DBAL changes
|
||||
5. **When writing tests**: Copy pattern from "Test Patterns" section
|
||||
6. **When unsure**: Check "Questions to Ask" (7 questions)
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
### Adding a new database entity
|
||||
1. Read: API-First DBAL Development pattern
|
||||
2. Check: DBAL-Specific Guidance (YAML → Types → Adapters)
|
||||
3. Reference: `dbal/docs/AGENTS.md` for detailed workflow
|
||||
|
||||
### Creating a new component feature
|
||||
1. Read: Generic Component Rendering pattern
|
||||
2. Reference: `RenderComponent.tsx` example
|
||||
3. Build: JSON config + use `RenderComponent` instead of TSX
|
||||
|
||||
### Fixing multi-tenancy bug
|
||||
1. Read: Multi-Tenant Safety section
|
||||
2. Check: "Common Mistakes" #2 (forgetting tenantId filter)
|
||||
3. Verify: Query includes `where('tenantId', currentTenant.id)`
|
||||
|
||||
### Adding test coverage
|
||||
1. Reference: "Test Patterns" section with `it.each()` example
|
||||
2. Run: `npm run test:check-functions` to verify coverage
|
||||
3. Generate: `npm run test:coverage:report`
|
||||
|
||||
## Metrics
|
||||
|
||||
- **Length**: ~160 lines (vs. original ~110 lines, +45% with critical new sections)
|
||||
- **Specificity**: 7 code examples (vs. 0 in original)
|
||||
- **Patterns documented**: 12 discoverable patterns extracted from codebase
|
||||
- **Common mistakes**: 6 explicit anti-patterns with solutions
|
||||
- **Key files referenced**: 9 files with specific line numbers
|
||||
- **Action items**: 7 specific questions to ask
|
||||
|
||||
## Files to Review
|
||||
|
||||
Agents should prioritize these when onboarding:
|
||||
|
||||
1. **Start**: `docs/architecture/5-level-system.md` (understand permissions)
|
||||
2. **Then**: `docs/architecture/packages.md` (understand modularity)
|
||||
3. **Then**: `src/lib/database.ts` (understand DB pattern)
|
||||
4. **Then**: `dbal/docs/AGENTS.md` (if working on DBAL)
|
||||
5. **Always**: `FUNCTION_TEST_COVERAGE.md` (for test requirements)
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Ready for AI agents to use
|
||||
**Last Updated**: December 25, 2025
|
||||
# Copilot Instructions Update Summary
|
||||
|
||||
## Generated: December 25, 2025
|
||||
|
||||
### File Updated
|
||||
`.github/copilot-instructions.md` - **~160 lines** of concise, actionable guidance for AI coding agents
|
||||
|
||||
### Analysis Approach
|
||||
|
||||
1. **Examined existing instructions**
|
||||
- `dbal/docs/AGENTS.md` (605 lines) - DBAL-specific agent development guide
|
||||
- `.github/copilot-instructions.md` (existing) - Original generic guidance
|
||||
|
||||
2. **Analyzed codebase patterns** through:
|
||||
- Database schema (`prisma/schema.prisma`) - Multi-tenant data model
|
||||
- Core libs: `database.ts`, `package-loader.ts`, `declarative-component-renderer.ts`
|
||||
- Test patterns: `schema-utils.test.ts` (441 lines, 63 parameterized tests)
|
||||
- Package system: `/packages/*/seed/` structure across 8 packages
|
||||
- Component patterns: `RenderComponent.tsx` (generic declarative renderer)
|
||||
- Security: `password-utils.ts`, `secure-db-layer.ts`, `sandboxed-lua-engine.ts`
|
||||
|
||||
3. **Discovered critical knowledge gaps** in original instructions:
|
||||
- No mention of DBAL architecture (critical for full codebase understanding)
|
||||
- Missing package loader workflow (`initializePackageSystem()`)
|
||||
- No guidance on parameterized testing pattern (100+ tests using `it.each()`)
|
||||
- Incomplete database pattern description
|
||||
- No mention of Fengari Lua integration specifics
|
||||
|
||||
## What's New in Updated Instructions
|
||||
|
||||
### 1. Architecture Overview Section
|
||||
**Why it matters**: Developers need to understand the 5-level permission system, DBAL's dual implementation (TS + C++), and multi-tenancy from day one.
|
||||
|
||||
```
|
||||
- 5-Level Permission System: Public → User → Admin → God → Supergod
|
||||
- DBAL: TypeScript SDK + C++ daemon with YAML contracts for language-agnostic APIs
|
||||
- Declarative Components: RenderComponent pattern for JSON-driven UIs
|
||||
- Package System: `/packages/{name}/seed/` self-contained modules
|
||||
- Multi-Tenancy: All queries filter by tenantId
|
||||
```
|
||||
|
||||
### 2. Critical Patterns (5 core patterns)
|
||||
**Why this section**: Previous instructions mixed patterns with conventions. These are the "must understand" patterns:
|
||||
|
||||
1. **API-First DBAL** - YAML → Types → TypeScript adapter → C++ adapter → Conformance tests
|
||||
2. **Generic Components** - `RenderComponent` with config instead of hardcoded TSX
|
||||
3. **Package Seeds** - `packages/{name}/seed/metadata.json` auto-loaded by `initializePackageSystem()`
|
||||
4. **Database Helpers** - Always use `Database.*` methods, never raw Prisma
|
||||
5. **Lua Sandboxing** - Scripts isolated, no `os`/`io`/`require` access
|
||||
|
||||
### 3. Test Patterns with Real Examples
|
||||
**Why new**: Original instructions said "write tests" without showing the actual pattern used in this codebase.
|
||||
|
||||
```typescript
|
||||
// Actual pattern from schema-utils.test.ts
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
```
|
||||
|
||||
### 4. DBAL-Specific Guidance
|
||||
**Why critical**: DBAL is 20% of the codebase. Agents need to know:
|
||||
- TypeScript impl = fast iteration
|
||||
- C++ impl = production security
|
||||
- Conformance tests = guarantee parity
|
||||
- YAML schemas = source of truth
|
||||
|
||||
### 5. Multi-Tenant Safety Patterns
|
||||
**Why essential**: Multi-tenancy bugs are catastrophic. Explicit examples:
|
||||
|
||||
```typescript
|
||||
// ❌ Never - exposes all tenants' data
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Always - isolates by tenant
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
## Discoverable Patterns Documented
|
||||
|
||||
### 1. Package Loading Workflow
|
||||
```
|
||||
initializePackageSystem()
|
||||
↓
|
||||
buildPackageRegistry() [reads /packages directory]
|
||||
↓
|
||||
exportAllPackagesForSeed() [extracts components, scripts, metadata]
|
||||
↓
|
||||
loadPackageComponents() [registers with declarative renderer]
|
||||
↓
|
||||
Package data available at runtime
|
||||
```
|
||||
|
||||
### 2. Seed Data Initialization
|
||||
- `src/seed-data/` directory with modular files: `users.ts`, `components.ts`, `workflows.ts`, `scripts.ts`, `pages.ts`, `packages.ts`
|
||||
- Each module has `initialize*()` async function
|
||||
- Called from `initializeAllSeedData()` in `App.tsx` on startup
|
||||
|
||||
### 3. Test Coverage Enforcement
|
||||
- Auto-generated coverage report: `FUNCTION_TEST_COVERAGE.md`
|
||||
- Check function coverage: `npm run test:check-functions`
|
||||
- Coverage report: `npm run test:coverage:report`
|
||||
- Parameterized test pattern reduces code duplication by ~60%
|
||||
|
||||
### 4. Component Size Limits
|
||||
- Hard limit: 150 LOC (except `RenderComponent.tsx` which uses recursive pattern)
|
||||
- Enforced by code review and linting patterns
|
||||
- Solution: Use generic `RenderComponent` + JSON config
|
||||
|
||||
## Connecting to Key Files
|
||||
|
||||
Instructions now reference:
|
||||
|
||||
| File | Purpose | Why Referenced |
|
||||
|------|---------|-----------------|
|
||||
| `dbal/docs/AGENTS.md` | DBAL development guide | Critical for DBAL changes |
|
||||
| `src/lib/database.ts` | Database operations | 1200+ LOC utility wrapper, required for all DB access |
|
||||
| `src/components/RenderComponent.tsx` | Generic renderer | 221 LOC example of declarative UI pattern |
|
||||
| `src/lib/schema-utils.test.ts` | Test examples | 63 tests showing parameterized pattern |
|
||||
| `docs/architecture/5-level-system.md` | Permission model | Understanding multi-level access control |
|
||||
| `docs/architecture/packages.md` | Package system | Understanding modular package structure |
|
||||
| `prisma/schema.prisma` | Data model | Multi-tenant schema structure |
|
||||
|
||||
## Sections Retained from Original
|
||||
|
||||
✅ Component size limits (< 150 LOC)
|
||||
✅ Functional components with hooks
|
||||
✅ `@/` absolute paths with shadcn/ui
|
||||
✅ Tailwind-only styling
|
||||
✅ SHA-512 password hashing
|
||||
✅ Sandbox Lua execution
|
||||
✅ Database-driven configuration preference
|
||||
|
||||
## New Guidance Not in Original
|
||||
|
||||
✅ DBAL dual-implementation architecture
|
||||
✅ Parameterized test patterns with examples
|
||||
✅ Package loader workflow
|
||||
✅ Multi-tenant query patterns (explicit examples)
|
||||
✅ Conformance test process for DBAL
|
||||
✅ API-First development (YAML → Types → Impl)
|
||||
✅ Fengari Lua integration specifics
|
||||
✅ Common mistakes with fixes
|
||||
|
||||
## How Agents Should Use This
|
||||
|
||||
1. **On startup**: Read "Architecture Overview" to understand the 4 pillars
|
||||
2. **Before implementation**: Check "Critical Patterns" (5 patterns) + relevant section
|
||||
3. **During code review**: Run through "Common Mistakes" checklist
|
||||
4. **When fixing bugs**: Check "DBAL-Specific Guidance" if involving DBAL changes
|
||||
5. **When writing tests**: Copy pattern from "Test Patterns" section
|
||||
6. **When unsure**: Check "Questions to Ask" (7 questions)
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
### Adding a new database entity
|
||||
1. Read: API-First DBAL Development pattern
|
||||
2. Check: DBAL-Specific Guidance (YAML → Types → Adapters)
|
||||
3. Reference: `dbal/docs/AGENTS.md` for detailed workflow
|
||||
|
||||
### Creating a new component feature
|
||||
1. Read: Generic Component Rendering pattern
|
||||
2. Reference: `RenderComponent.tsx` example
|
||||
3. Build: JSON config + use `RenderComponent` instead of TSX
|
||||
|
||||
### Fixing multi-tenancy bug
|
||||
1. Read: Multi-Tenant Safety section
|
||||
2. Check: "Common Mistakes" #2 (forgetting tenantId filter)
|
||||
3. Verify: Query includes `where('tenantId', currentTenant.id)`
|
||||
|
||||
### Adding test coverage
|
||||
1. Reference: "Test Patterns" section with `it.each()` example
|
||||
2. Run: `npm run test:check-functions` to verify coverage
|
||||
3. Generate: `npm run test:coverage:report`
|
||||
|
||||
## Metrics
|
||||
|
||||
- **Length**: ~160 lines (vs. original ~110 lines, +45% with critical new sections)
|
||||
- **Specificity**: 7 code examples (vs. 0 in original)
|
||||
- **Patterns documented**: 12 discoverable patterns extracted from codebase
|
||||
- **Common mistakes**: 6 explicit anti-patterns with solutions
|
||||
- **Key files referenced**: 9 files with specific line numbers
|
||||
- **Action items**: 7 specific questions to ask
|
||||
|
||||
## Files to Review
|
||||
|
||||
Agents should prioritize these when onboarding:
|
||||
|
||||
1. **Start**: `docs/architecture/5-level-system.md` (understand permissions)
|
||||
2. **Then**: `docs/architecture/packages.md` (understand modularity)
|
||||
3. **Then**: `src/lib/database.ts` (understand DB pattern)
|
||||
4. **Then**: `dbal/docs/AGENTS.md` (if working on DBAL)
|
||||
5. **Always**: `FUNCTION_TEST_COVERAGE.md` (for test requirements)
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Ready for AI agents to use
|
||||
**Last Updated**: December 25, 2025
|
||||
|
||||
864
.github/COPILOT_SDLC_SUMMARY.md
vendored
864
.github/COPILOT_SDLC_SUMMARY.md
vendored
@@ -1,432 +1,432 @@
|
||||
# GitHub Copilot SDLC Integration Summary
|
||||
|
||||
## Overview
|
||||
|
||||
MetaBuilder's GitHub workflows are comprehensively integrated with **GitHub Copilot** to assist throughout the entire Software Development Lifecycle (SDLC). This document provides an overview of how Copilot enhances each phase of development.
|
||||
|
||||
## SDLC Phase Coverage
|
||||
|
||||
### ✅ Phase 1: Planning & Design
|
||||
|
||||
**Workflows:**
|
||||
- `planning.yml` - Architecture review, PRD alignment, implementation guidance
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Architecture Review**: Analyzes feature requests against declarative-first principles
|
||||
- ✅ **PRD Alignment**: Checks if features align with project mission (95% declarative, multi-tenant)
|
||||
- ✅ **Design Checklist**: Provides comprehensive checklist for feature planning
|
||||
- ✅ **Multi-Tenant Validation**: Ensures tenant isolation is considered
|
||||
- ✅ **Permission Level Planning**: Validates which levels (1-5) should access the feature
|
||||
- ✅ **Declarative Assessment**: Suggests JSON/Lua approaches over TypeScript
|
||||
- ✅ **Package Structure Guidance**: Recommends package-based implementation when appropriate
|
||||
|
||||
**How It Works:**
|
||||
1. Developer creates issue with `enhancement` or `feature-request` label
|
||||
2. Workflow automatically analyzes the request
|
||||
3. Provides architectural suggestions and questions
|
||||
4. Creates design checklist
|
||||
5. Suggests PRD concepts to review
|
||||
6. When labeled `ready-to-implement`, provides step-by-step implementation plan
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
Issue: "Add real-time notifications system"
|
||||
↓
|
||||
Copilot suggests:
|
||||
- Implement as declarative component with JSON + Lua
|
||||
- Store notification config in database
|
||||
- Consider tenant-specific notification preferences
|
||||
- Plan for Level 2+ permission access
|
||||
- Create /packages/notifications/ structure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 2: Development
|
||||
|
||||
**Workflows:**
|
||||
- `development.yml` - Continuous quality feedback, architectural compliance, refactoring suggestions
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Real-Time Code Metrics**: Tracks TypeScript vs JSON/Lua ratio
|
||||
- ✅ **Component Size Monitoring**: Flags files exceeding 150 LOC
|
||||
- ✅ **Architectural Compliance**: Validates adherence to declarative principles
|
||||
- ✅ **Refactoring Opportunities**: Identifies code that could be more declarative
|
||||
- ✅ **Configuration Detection**: Finds hardcoded values that should be in database
|
||||
- ✅ **@copilot Mentions**: Responds to developer questions with contextual guidance
|
||||
- ✅ **Pattern Recognition**: Suggests generic renderers over hardcoded components
|
||||
- ✅ **Seed Data Validation**: Checks if database changes have corresponding seed updates
|
||||
|
||||
**How It Works:**
|
||||
1. Developer pushes to feature branch
|
||||
2. Workflow analyzes code changes
|
||||
3. Calculates declarative ratio (JSON + Lua / Total TS files)
|
||||
4. Identifies large components, hardcoded values, new TSX files
|
||||
5. Posts feedback comment with metrics and suggestions
|
||||
6. Updates on each push with latest analysis
|
||||
|
||||
**Metrics Tracked:**
|
||||
- Total TypeScript files
|
||||
- Files exceeding 150 LOC
|
||||
- JSON configuration files
|
||||
- Lua scripts
|
||||
- Declarative ratio percentage
|
||||
- Hardcoded constants
|
||||
- New component files
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Push to feature/notifications
|
||||
↓
|
||||
Copilot reports:
|
||||
- TypeScript files: 45
|
||||
- Files >150 LOC: 2 ⚠️
|
||||
- JSON config files: 12
|
||||
- Lua scripts: 8
|
||||
- Declarative ratio: 44.4%
|
||||
- Suggestion: NotificationPanel.tsx (180 LOC) could be split
|
||||
- Suggestion: Move hardcoded notification types to database
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 3: Testing & Code Review
|
||||
|
||||
**Workflows:**
|
||||
- `ci.yml` - Lint, build, E2E tests
|
||||
- `code-review.yml` - Automated security and quality review
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Security Scanning**: Detects eval(), innerHTML, XSS risks
|
||||
- ✅ **Code Quality Checks**: Identifies console.log, debugger, any types
|
||||
- ✅ **Best Practice Validation**: React hooks, empty dependencies
|
||||
- ✅ **File Size Warnings**: Flags large changesets
|
||||
- ✅ **Auto-Approval**: Approves PRs with no blocking issues
|
||||
- ✅ **Label Management**: Adds appropriate labels (needs-changes, ready-for-review)
|
||||
- ✅ **Lint Error Reporting**: Displays ESLint issues inline
|
||||
- ✅ **Test Validation**: Ensures E2E tests pass
|
||||
|
||||
**Review Criteria:**
|
||||
- Security vulnerabilities (eval, innerHTML, dangerouslySetInnerHTML)
|
||||
- Debug code (console.log, debugger)
|
||||
- Type safety (any types)
|
||||
- React best practices (useEffect dependencies)
|
||||
- File sizes (>500 lines)
|
||||
- Lint errors
|
||||
|
||||
**Example:**
|
||||
```
|
||||
PR opened: "Add notifications"
|
||||
↓
|
||||
Copilot reviews:
|
||||
✅ No security issues
|
||||
⚠️ Warning: Console.log in NotificationService.tsx
|
||||
💡 Suggestion: Replace 'any' types with specific interfaces
|
||||
⚠️ Warning: NotificationPanel.tsx has 180 additions
|
||||
✅ Status: APPROVED (fix warnings before merge)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 4: Integration & Merge
|
||||
|
||||
**Workflows:**
|
||||
- `pr-management.yml` - PR labeling, description validation, issue linking
|
||||
- `merge-conflict-check.yml` - Conflict detection
|
||||
- `auto-merge.yml` - Automated merging
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Auto-Labeling**: Categorizes PRs by affected areas (ui, tests, docs, workflows)
|
||||
- ✅ **Size Classification**: Labels as small/medium/large
|
||||
- ✅ **Description Quality**: Validates PR has adequate description
|
||||
- ✅ **Issue Linking**: Connects PRs to related issues
|
||||
- ✅ **Conflict Detection**: Alerts when merge conflicts exist with @copilot mention
|
||||
- ✅ **Auto-Merge**: Merges approved PRs that pass all checks
|
||||
- ✅ **Branch Cleanup**: Deletes branches after successful merge
|
||||
|
||||
**How It Works:**
|
||||
1. PR is opened/updated
|
||||
2. Auto-labeled based on changed files
|
||||
3. Description validated for quality
|
||||
4. Related issues linked automatically
|
||||
5. Conflicts checked against base branch
|
||||
6. Once approved + tests pass → auto-merged
|
||||
7. Branch deleted automatically
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 5: Deployment
|
||||
|
||||
**Workflows:**
|
||||
- `deployment.yml` - Pre-deployment validation, health checks, monitoring
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Pre-Deployment Validation**: Schema validation, security audit, size check
|
||||
- ✅ **Breaking Change Detection**: Identifies commits with breaking changes
|
||||
- ✅ **Deployment Notes**: Auto-generates categorized release notes
|
||||
- ✅ **Health Checks**: Verifies build integrity and critical files
|
||||
- ✅ **Deployment Tracking**: Creates monitoring issues for releases
|
||||
- ✅ **Security Audit**: Scans dependencies for vulnerabilities
|
||||
- ✅ **Environment Validation**: Checks required configuration exists
|
||||
|
||||
**Deployment Checklist:**
|
||||
- Database schema validity
|
||||
- Security vulnerabilities (npm audit)
|
||||
- Build size optimization
|
||||
- Environment configuration
|
||||
- Breaking changes documented
|
||||
- Health check verification
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Release: v2.0.0
|
||||
↓
|
||||
Copilot generates:
|
||||
- Deployment Summary with categorized commits
|
||||
- Breaking changes alert (2 found)
|
||||
- New features list (8)
|
||||
- Bug fixes list (12)
|
||||
- Creates tracking issue with 48hr monitoring plan
|
||||
- Health checks: ✅ All passed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 6: Maintenance & Operations
|
||||
|
||||
**Workflows:**
|
||||
- `issue-triage.yml` - Issue categorization, auto-fix suggestions
|
||||
- `dependabot.yml` - Dependency updates
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Automatic Triage**: Categorizes issues by type and priority
|
||||
- ✅ **AI-Fixable Detection**: Identifies issues suitable for automated fixes
|
||||
- ✅ **Good First Issue**: Flags beginner-friendly issues
|
||||
- ✅ **Auto-Fix Branch Creation**: Creates branches for automated fixes
|
||||
- ✅ **Dependency Monitoring**: Daily npm updates, weekly devcontainer updates
|
||||
- ✅ **Security Vulnerability Tracking**: Auto-creates issues for critical CVEs
|
||||
|
||||
**Issue Categories:**
|
||||
- Type: bug, enhancement, documentation, testing, security, performance
|
||||
- Priority: high, medium, low
|
||||
- Difficulty: good first issue
|
||||
- Automation: ai-fixable, auto-fix
|
||||
|
||||
---
|
||||
|
||||
## Copilot Interaction Patterns
|
||||
|
||||
### 1. In Issues
|
||||
|
||||
**Mention Patterns:**
|
||||
```markdown
|
||||
@copilot implement this issue
|
||||
@copilot review the architecture
|
||||
@copilot suggest testing strategy
|
||||
@copilot help with database schema
|
||||
@copilot fix this issue
|
||||
```
|
||||
|
||||
**Response:** Context-aware guidance based on:
|
||||
- Copilot Instructions (.github/copilot-instructions.md)
|
||||
- docs/getting-started/PRD.md project mission
|
||||
- Existing package structure
|
||||
- Architectural principles
|
||||
|
||||
### 2. In Pull Requests
|
||||
|
||||
**Automatic Feedback:**
|
||||
- Code metrics on every push
|
||||
- Refactoring suggestions
|
||||
- Architectural compliance
|
||||
- Security review
|
||||
- Quality assessment
|
||||
|
||||
**Mention for:**
|
||||
- Specific implementation questions
|
||||
- Refactoring guidance
|
||||
- Testing approaches
|
||||
- Architectural decisions
|
||||
|
||||
### 3. In Your IDE
|
||||
|
||||
**Context Files:**
|
||||
- `.github/copilot-instructions.md` - Comprehensive project guidelines
|
||||
- `docs/getting-started/PRD.md` - Feature context and project mission
|
||||
- `/packages/*/seed/` - Existing patterns to follow
|
||||
- `prisma/schema.prisma` - Database structure
|
||||
|
||||
**Best Practices:**
|
||||
- Reference docs/getting-started/PRD.md when asking about features
|
||||
- Show existing patterns when requesting new code
|
||||
- Ask about architectural decisions before implementing
|
||||
- Request declarative approaches explicitly
|
||||
|
||||
---
|
||||
|
||||
## Measurement & Metrics
|
||||
|
||||
### Code Quality Metrics
|
||||
|
||||
**Tracked Automatically:**
|
||||
- Declarative ratio: `(JSON files + Lua scripts) / TypeScript files * 100%`
|
||||
- Component size: Files exceeding 150 LOC
|
||||
- TypeScript usage: Total .ts/.tsx files
|
||||
- Configuration: Database-driven vs hardcoded
|
||||
|
||||
**Goals:**
|
||||
- Declarative ratio: >50%
|
||||
- Component size: <150 LOC
|
||||
- TypeScript: Minimal (infrastructure only)
|
||||
- Configuration: 100% database-driven
|
||||
|
||||
### SDLC Coverage Metrics
|
||||
|
||||
**Phase Coverage:**
|
||||
- ✅ Planning: Architecture review, PRD alignment
|
||||
- ✅ Development: Continuous feedback, refactoring
|
||||
- ✅ Testing: Security scan, quality checks
|
||||
- ✅ Integration: Auto-merge, conflict resolution
|
||||
- ✅ Deployment: Validation, health checks
|
||||
- ✅ Maintenance: Triage, auto-fix, dependencies
|
||||
|
||||
**Coverage: 100% of SDLC phases**
|
||||
|
||||
### Automation Metrics
|
||||
|
||||
**Automated Actions:**
|
||||
- Issue triage and labeling
|
||||
- PR categorization
|
||||
- Code review and approval
|
||||
- Merge and branch cleanup
|
||||
- Deployment validation
|
||||
- Security vulnerability tracking
|
||||
- Dependency updates
|
||||
|
||||
**Human Intervention Required:**
|
||||
- Final approval for deployment
|
||||
- Resolution of blocking issues
|
||||
- Complex architectural decisions
|
||||
- Multi-tenant design considerations
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### 1. Copilot Instructions
|
||||
**File:** `.github/copilot-instructions.md`
|
||||
|
||||
**Contains:**
|
||||
- Project context and architecture
|
||||
- Code conventions (TS, React, Lua, Prisma)
|
||||
- Development workflow guidance
|
||||
- Security considerations
|
||||
- Common patterns and examples
|
||||
- Integration with workflows
|
||||
- Useful commands
|
||||
|
||||
### 2. Workflow Definitions
|
||||
**Directory:** `.github/workflows/`
|
||||
|
||||
**Files:**
|
||||
- `ci.yml` - CI/CD pipeline
|
||||
- `code-review.yml` - Automated review
|
||||
- `auto-merge.yml` - Merge automation
|
||||
- `issue-triage.yml` - Issue management
|
||||
- `pr-management.yml` - PR automation
|
||||
- `merge-conflict-check.yml` - Conflict detection
|
||||
- `planning.yml` - Planning assistance *(NEW)*
|
||||
- `development.yml` - Development feedback *(NEW)*
|
||||
- `deployment.yml` - Deployment automation *(NEW)*
|
||||
|
||||
### 3. Documentation
|
||||
**Files:**
|
||||
- `.github/workflows/README.md` - Workflow documentation
|
||||
- `docs/getting-started/PRD.md` - Product requirements
|
||||
- `docs/security/SECURITY.md` - Security policies
|
||||
- `docs/README.md` - Project overview
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### For Developers
|
||||
|
||||
1. **Faster Onboarding**: Copilot guides new developers with architectural principles
|
||||
2. **Consistent Quality**: Automated checks enforce coding standards
|
||||
3. **Reduced Review Time**: Many issues caught automatically
|
||||
4. **Better Architecture**: Continuous feedback on declarative principles
|
||||
5. **Security Awareness**: Proactive vulnerability detection
|
||||
6. **Learning Tool**: Suggestions teach best practices
|
||||
|
||||
### For Teams
|
||||
|
||||
1. **Standardized Process**: Every issue/PR follows same workflow
|
||||
2. **Knowledge Sharing**: Architectural principles documented and enforced
|
||||
3. **Reduced Technical Debt**: Refactoring suggestions identify improvement areas
|
||||
4. **Faster Iteration**: Auto-merge reduces bottlenecks
|
||||
5. **Better Tracking**: Deployment and issue tracking automated
|
||||
6. **Visibility**: Metrics show declarative ratio and code quality trends
|
||||
|
||||
### For the Project
|
||||
|
||||
1. **Architectural Integrity**: Maintains 95% declarative goal
|
||||
2. **Scalability**: Package-based structure enforced
|
||||
3. **Multi-Tenant Safety**: Tenant considerations validated
|
||||
4. **Security**: Continuous vulnerability monitoring
|
||||
5. **Documentation**: Auto-generated release notes and tracking
|
||||
6. **Quality**: Consistent enforcement of 150 LOC limit
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Potential Additions
|
||||
|
||||
1. **Copilot Workspace Integration**: Direct IDE integration with workflow context
|
||||
2. **AI-Generated Tests**: Auto-generate E2E tests from issue descriptions
|
||||
3. **Performance Monitoring**: Track bundle size, render performance over time
|
||||
4. **Accessibility Checks**: Automated a11y validation in PRs
|
||||
5. **Visual Regression Testing**: Screenshot comparison for UI changes
|
||||
6. **Lua Linting**: Custom linter for Lua scripts following project patterns
|
||||
7. **Package Validation**: Verify package structure meets standards
|
||||
8. **Multi-Tenant Testing**: Automated tenant isolation verification
|
||||
|
||||
### Metrics Dashboard
|
||||
|
||||
**Potential Features:**
|
||||
- Declarative ratio trend over time
|
||||
- Average component size
|
||||
- PR merge time
|
||||
- Auto-fix success rate
|
||||
- Security vulnerability resolution time
|
||||
- Test coverage trends
|
||||
- Deployment frequency
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
MetaBuilder's GitHub workflows provide **comprehensive GitHub Copilot integration across all SDLC phases**:
|
||||
|
||||
✅ **Planning** - Architecture review and PRD alignment
|
||||
✅ **Development** - Continuous quality feedback and refactoring
|
||||
✅ **Testing** - Security scanning and quality validation
|
||||
✅ **Integration** - Auto-labeling, review, and merge
|
||||
✅ **Deployment** - Validation, health checks, and tracking
|
||||
✅ **Maintenance** - Issue triage, auto-fix, and dependency management
|
||||
|
||||
**Key Achievements:**
|
||||
- 100% SDLC phase coverage
|
||||
- Automated enforcement of declarative-first principles
|
||||
- Context-aware @copilot assistance throughout development
|
||||
- Comprehensive metrics tracking (declarative ratio, component size)
|
||||
- Security-first approach with continuous vulnerability monitoring
|
||||
- Self-documenting with auto-generated deployment notes
|
||||
|
||||
**Documentation:**
|
||||
- Copilot Instructions: `.github/copilot-instructions.md`
|
||||
- Workflow Guide: `.github/workflows/README.md`
|
||||
- This Summary: `.github/COPILOT_SDLC_SUMMARY.md`
|
||||
|
||||
The workflows ensure that GitHub Copilot can assist developers at every stage, from initial planning through deployment and maintenance, while maintaining the project's architectural integrity and quality standards.
|
||||
# GitHub Copilot SDLC Integration Summary
|
||||
|
||||
## Overview
|
||||
|
||||
MetaBuilder's GitHub workflows are comprehensively integrated with **GitHub Copilot** to assist throughout the entire Software Development Lifecycle (SDLC). This document provides an overview of how Copilot enhances each phase of development.
|
||||
|
||||
## SDLC Phase Coverage
|
||||
|
||||
### ✅ Phase 1: Planning & Design
|
||||
|
||||
**Workflows:**
|
||||
- `planning.yml` - Architecture review, PRD alignment, implementation guidance
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Architecture Review**: Analyzes feature requests against declarative-first principles
|
||||
- ✅ **PRD Alignment**: Checks if features align with project mission (95% declarative, multi-tenant)
|
||||
- ✅ **Design Checklist**: Provides comprehensive checklist for feature planning
|
||||
- ✅ **Multi-Tenant Validation**: Ensures tenant isolation is considered
|
||||
- ✅ **Permission Level Planning**: Validates which levels (1-5) should access the feature
|
||||
- ✅ **Declarative Assessment**: Suggests JSON/Lua approaches over TypeScript
|
||||
- ✅ **Package Structure Guidance**: Recommends package-based implementation when appropriate
|
||||
|
||||
**How It Works:**
|
||||
1. Developer creates issue with `enhancement` or `feature-request` label
|
||||
2. Workflow automatically analyzes the request
|
||||
3. Provides architectural suggestions and questions
|
||||
4. Creates design checklist
|
||||
5. Suggests PRD concepts to review
|
||||
6. When labeled `ready-to-implement`, provides step-by-step implementation plan
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
Issue: "Add real-time notifications system"
|
||||
↓
|
||||
Copilot suggests:
|
||||
- Implement as declarative component with JSON + Lua
|
||||
- Store notification config in database
|
||||
- Consider tenant-specific notification preferences
|
||||
- Plan for Level 2+ permission access
|
||||
- Create /packages/notifications/ structure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 2: Development
|
||||
|
||||
**Workflows:**
|
||||
- `development.yml` - Continuous quality feedback, architectural compliance, refactoring suggestions
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Real-Time Code Metrics**: Tracks TypeScript vs JSON/Lua ratio
|
||||
- ✅ **Component Size Monitoring**: Flags files exceeding 150 LOC
|
||||
- ✅ **Architectural Compliance**: Validates adherence to declarative principles
|
||||
- ✅ **Refactoring Opportunities**: Identifies code that could be more declarative
|
||||
- ✅ **Configuration Detection**: Finds hardcoded values that should be in database
|
||||
- ✅ **@copilot Mentions**: Responds to developer questions with contextual guidance
|
||||
- ✅ **Pattern Recognition**: Suggests generic renderers over hardcoded components
|
||||
- ✅ **Seed Data Validation**: Checks if database changes have corresponding seed updates
|
||||
|
||||
**How It Works:**
|
||||
1. Developer pushes to feature branch
|
||||
2. Workflow analyzes code changes
|
||||
3. Calculates declarative ratio (JSON + Lua / Total TS files)
|
||||
4. Identifies large components, hardcoded values, new TSX files
|
||||
5. Posts feedback comment with metrics and suggestions
|
||||
6. Updates on each push with latest analysis
|
||||
|
||||
**Metrics Tracked:**
|
||||
- Total TypeScript files
|
||||
- Files exceeding 150 LOC
|
||||
- JSON configuration files
|
||||
- Lua scripts
|
||||
- Declarative ratio percentage
|
||||
- Hardcoded constants
|
||||
- New component files
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Push to feature/notifications
|
||||
↓
|
||||
Copilot reports:
|
||||
- TypeScript files: 45
|
||||
- Files >150 LOC: 2 ⚠️
|
||||
- JSON config files: 12
|
||||
- Lua scripts: 8
|
||||
- Declarative ratio: 44.4%
|
||||
- Suggestion: NotificationPanel.tsx (180 LOC) could be split
|
||||
- Suggestion: Move hardcoded notification types to database
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 3: Testing & Code Review
|
||||
|
||||
**Workflows:**
|
||||
- `ci.yml` - Lint, build, E2E tests
|
||||
- `code-review.yml` - Automated security and quality review
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Security Scanning**: Detects eval(), innerHTML, XSS risks
|
||||
- ✅ **Code Quality Checks**: Identifies console.log, debugger, any types
|
||||
- ✅ **Best Practice Validation**: React hooks, empty dependencies
|
||||
- ✅ **File Size Warnings**: Flags large changesets
|
||||
- ✅ **Auto-Approval**: Approves PRs with no blocking issues
|
||||
- ✅ **Label Management**: Adds appropriate labels (needs-changes, ready-for-review)
|
||||
- ✅ **Lint Error Reporting**: Displays ESLint issues inline
|
||||
- ✅ **Test Validation**: Ensures E2E tests pass
|
||||
|
||||
**Review Criteria:**
|
||||
- Security vulnerabilities (eval, innerHTML, dangerouslySetInnerHTML)
|
||||
- Debug code (console.log, debugger)
|
||||
- Type safety (any types)
|
||||
- React best practices (useEffect dependencies)
|
||||
- File sizes (>500 lines)
|
||||
- Lint errors
|
||||
|
||||
**Example:**
|
||||
```
|
||||
PR opened: "Add notifications"
|
||||
↓
|
||||
Copilot reviews:
|
||||
✅ No security issues
|
||||
⚠️ Warning: Console.log in NotificationService.tsx
|
||||
💡 Suggestion: Replace 'any' types with specific interfaces
|
||||
⚠️ Warning: NotificationPanel.tsx has 180 additions
|
||||
✅ Status: APPROVED (fix warnings before merge)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 4: Integration & Merge
|
||||
|
||||
**Workflows:**
|
||||
- `pr-management.yml` - PR labeling, description validation, issue linking
|
||||
- `merge-conflict-check.yml` - Conflict detection
|
||||
- `auto-merge.yml` - Automated merging
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Auto-Labeling**: Categorizes PRs by affected areas (ui, tests, docs, workflows)
|
||||
- ✅ **Size Classification**: Labels as small/medium/large
|
||||
- ✅ **Description Quality**: Validates PR has adequate description
|
||||
- ✅ **Issue Linking**: Connects PRs to related issues
|
||||
- ✅ **Conflict Detection**: Alerts when merge conflicts exist with @copilot mention
|
||||
- ✅ **Auto-Merge**: Merges approved PRs that pass all checks
|
||||
- ✅ **Branch Cleanup**: Deletes branches after successful merge
|
||||
|
||||
**How It Works:**
|
||||
1. PR is opened/updated
|
||||
2. Auto-labeled based on changed files
|
||||
3. Description validated for quality
|
||||
4. Related issues linked automatically
|
||||
5. Conflicts checked against base branch
|
||||
6. Once approved + tests pass → auto-merged
|
||||
7. Branch deleted automatically
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 5: Deployment
|
||||
|
||||
**Workflows:**
|
||||
- `deployment.yml` - Pre-deployment validation, health checks, monitoring
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Pre-Deployment Validation**: Schema validation, security audit, size check
|
||||
- ✅ **Breaking Change Detection**: Identifies commits with breaking changes
|
||||
- ✅ **Deployment Notes**: Auto-generates categorized release notes
|
||||
- ✅ **Health Checks**: Verifies build integrity and critical files
|
||||
- ✅ **Deployment Tracking**: Creates monitoring issues for releases
|
||||
- ✅ **Security Audit**: Scans dependencies for vulnerabilities
|
||||
- ✅ **Environment Validation**: Checks required configuration exists
|
||||
|
||||
**Deployment Checklist:**
|
||||
- Database schema validity
|
||||
- Security vulnerabilities (npm audit)
|
||||
- Build size optimization
|
||||
- Environment configuration
|
||||
- Breaking changes documented
|
||||
- Health check verification
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Release: v2.0.0
|
||||
↓
|
||||
Copilot generates:
|
||||
- Deployment Summary with categorized commits
|
||||
- Breaking changes alert (2 found)
|
||||
- New features list (8)
|
||||
- Bug fixes list (12)
|
||||
- Creates tracking issue with 48hr monitoring plan
|
||||
- Health checks: ✅ All passed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 6: Maintenance & Operations
|
||||
|
||||
**Workflows:**
|
||||
- `issue-triage.yml` - Issue categorization, auto-fix suggestions
|
||||
- `dependabot.yml` - Dependency updates
|
||||
|
||||
**Copilot Features:**
|
||||
- ✅ **Automatic Triage**: Categorizes issues by type and priority
|
||||
- ✅ **AI-Fixable Detection**: Identifies issues suitable for automated fixes
|
||||
- ✅ **Good First Issue**: Flags beginner-friendly issues
|
||||
- ✅ **Auto-Fix Branch Creation**: Creates branches for automated fixes
|
||||
- ✅ **Dependency Monitoring**: Daily npm updates, weekly devcontainer updates
|
||||
- ✅ **Security Vulnerability Tracking**: Auto-creates issues for critical CVEs
|
||||
|
||||
**Issue Categories:**
|
||||
- Type: bug, enhancement, documentation, testing, security, performance
|
||||
- Priority: high, medium, low
|
||||
- Difficulty: good first issue
|
||||
- Automation: ai-fixable, auto-fix
|
||||
|
||||
---
|
||||
|
||||
## Copilot Interaction Patterns
|
||||
|
||||
### 1. In Issues
|
||||
|
||||
**Mention Patterns:**
|
||||
```markdown
|
||||
@copilot implement this issue
|
||||
@copilot review the architecture
|
||||
@copilot suggest testing strategy
|
||||
@copilot help with database schema
|
||||
@copilot fix this issue
|
||||
```
|
||||
|
||||
**Response:** Context-aware guidance based on:
|
||||
- Copilot Instructions (.github/copilot-instructions.md)
|
||||
- docs/getting-started/PRD.md project mission
|
||||
- Existing package structure
|
||||
- Architectural principles
|
||||
|
||||
### 2. In Pull Requests
|
||||
|
||||
**Automatic Feedback:**
|
||||
- Code metrics on every push
|
||||
- Refactoring suggestions
|
||||
- Architectural compliance
|
||||
- Security review
|
||||
- Quality assessment
|
||||
|
||||
**Mention for:**
|
||||
- Specific implementation questions
|
||||
- Refactoring guidance
|
||||
- Testing approaches
|
||||
- Architectural decisions
|
||||
|
||||
### 3. In Your IDE
|
||||
|
||||
**Context Files:**
|
||||
- `.github/copilot-instructions.md` - Comprehensive project guidelines
|
||||
- `docs/getting-started/PRD.md` - Feature context and project mission
|
||||
- `/packages/*/seed/` - Existing patterns to follow
|
||||
- `prisma/schema.prisma` - Database structure
|
||||
|
||||
**Best Practices:**
|
||||
- Reference docs/getting-started/PRD.md when asking about features
|
||||
- Show existing patterns when requesting new code
|
||||
- Ask about architectural decisions before implementing
|
||||
- Request declarative approaches explicitly
|
||||
|
||||
---
|
||||
|
||||
## Measurement & Metrics
|
||||
|
||||
### Code Quality Metrics
|
||||
|
||||
**Tracked Automatically:**
|
||||
- Declarative ratio: `(JSON files + Lua scripts) / TypeScript files * 100%`
|
||||
- Component size: Files exceeding 150 LOC
|
||||
- TypeScript usage: Total .ts/.tsx files
|
||||
- Configuration: Database-driven vs hardcoded
|
||||
|
||||
**Goals:**
|
||||
- Declarative ratio: >50%
|
||||
- Component size: <150 LOC
|
||||
- TypeScript: Minimal (infrastructure only)
|
||||
- Configuration: 100% database-driven
|
||||
|
||||
### SDLC Coverage Metrics
|
||||
|
||||
**Phase Coverage:**
|
||||
- ✅ Planning: Architecture review, PRD alignment
|
||||
- ✅ Development: Continuous feedback, refactoring
|
||||
- ✅ Testing: Security scan, quality checks
|
||||
- ✅ Integration: Auto-merge, conflict resolution
|
||||
- ✅ Deployment: Validation, health checks
|
||||
- ✅ Maintenance: Triage, auto-fix, dependencies
|
||||
|
||||
**Coverage: 100% of SDLC phases**
|
||||
|
||||
### Automation Metrics
|
||||
|
||||
**Automated Actions:**
|
||||
- Issue triage and labeling
|
||||
- PR categorization
|
||||
- Code review and approval
|
||||
- Merge and branch cleanup
|
||||
- Deployment validation
|
||||
- Security vulnerability tracking
|
||||
- Dependency updates
|
||||
|
||||
**Human Intervention Required:**
|
||||
- Final approval for deployment
|
||||
- Resolution of blocking issues
|
||||
- Complex architectural decisions
|
||||
- Multi-tenant design considerations
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### 1. Copilot Instructions
|
||||
**File:** `.github/copilot-instructions.md`
|
||||
|
||||
**Contains:**
|
||||
- Project context and architecture
|
||||
- Code conventions (TS, React, Lua, Prisma)
|
||||
- Development workflow guidance
|
||||
- Security considerations
|
||||
- Common patterns and examples
|
||||
- Integration with workflows
|
||||
- Useful commands
|
||||
|
||||
### 2. Workflow Definitions
|
||||
**Directory:** `.github/workflows/`
|
||||
|
||||
**Files:**
|
||||
- `ci.yml` - CI/CD pipeline
|
||||
- `code-review.yml` - Automated review
|
||||
- `auto-merge.yml` - Merge automation
|
||||
- `issue-triage.yml` - Issue management
|
||||
- `pr-management.yml` - PR automation
|
||||
- `merge-conflict-check.yml` - Conflict detection
|
||||
- `planning.yml` - Planning assistance *(NEW)*
|
||||
- `development.yml` - Development feedback *(NEW)*
|
||||
- `deployment.yml` - Deployment automation *(NEW)*
|
||||
|
||||
### 3. Documentation
|
||||
**Files:**
|
||||
- `.github/workflows/README.md` - Workflow documentation
|
||||
- `docs/getting-started/PRD.md` - Product requirements
|
||||
- `docs/security/SECURITY.md` - Security policies
|
||||
- `docs/README.md` - Project overview
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### For Developers
|
||||
|
||||
1. **Faster Onboarding**: Copilot guides new developers with architectural principles
|
||||
2. **Consistent Quality**: Automated checks enforce coding standards
|
||||
3. **Reduced Review Time**: Many issues caught automatically
|
||||
4. **Better Architecture**: Continuous feedback on declarative principles
|
||||
5. **Security Awareness**: Proactive vulnerability detection
|
||||
6. **Learning Tool**: Suggestions teach best practices
|
||||
|
||||
### For Teams
|
||||
|
||||
1. **Standardized Process**: Every issue/PR follows same workflow
|
||||
2. **Knowledge Sharing**: Architectural principles documented and enforced
|
||||
3. **Reduced Technical Debt**: Refactoring suggestions identify improvement areas
|
||||
4. **Faster Iteration**: Auto-merge reduces bottlenecks
|
||||
5. **Better Tracking**: Deployment and issue tracking automated
|
||||
6. **Visibility**: Metrics show declarative ratio and code quality trends
|
||||
|
||||
### For the Project
|
||||
|
||||
1. **Architectural Integrity**: Maintains 95% declarative goal
|
||||
2. **Scalability**: Package-based structure enforced
|
||||
3. **Multi-Tenant Safety**: Tenant considerations validated
|
||||
4. **Security**: Continuous vulnerability monitoring
|
||||
5. **Documentation**: Auto-generated release notes and tracking
|
||||
6. **Quality**: Consistent enforcement of 150 LOC limit
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Potential Additions
|
||||
|
||||
1. **Copilot Workspace Integration**: Direct IDE integration with workflow context
|
||||
2. **AI-Generated Tests**: Auto-generate E2E tests from issue descriptions
|
||||
3. **Performance Monitoring**: Track bundle size, render performance over time
|
||||
4. **Accessibility Checks**: Automated a11y validation in PRs
|
||||
5. **Visual Regression Testing**: Screenshot comparison for UI changes
|
||||
6. **Lua Linting**: Custom linter for Lua scripts following project patterns
|
||||
7. **Package Validation**: Verify package structure meets standards
|
||||
8. **Multi-Tenant Testing**: Automated tenant isolation verification
|
||||
|
||||
### Metrics Dashboard
|
||||
|
||||
**Potential Features:**
|
||||
- Declarative ratio trend over time
|
||||
- Average component size
|
||||
- PR merge time
|
||||
- Auto-fix success rate
|
||||
- Security vulnerability resolution time
|
||||
- Test coverage trends
|
||||
- Deployment frequency
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
MetaBuilder's GitHub workflows provide **comprehensive GitHub Copilot integration across all SDLC phases**:
|
||||
|
||||
✅ **Planning** - Architecture review and PRD alignment
|
||||
✅ **Development** - Continuous quality feedback and refactoring
|
||||
✅ **Testing** - Security scanning and quality validation
|
||||
✅ **Integration** - Auto-labeling, review, and merge
|
||||
✅ **Deployment** - Validation, health checks, and tracking
|
||||
✅ **Maintenance** - Issue triage, auto-fix, and dependency management
|
||||
|
||||
**Key Achievements:**
|
||||
- 100% SDLC phase coverage
|
||||
- Automated enforcement of declarative-first principles
|
||||
- Context-aware @copilot assistance throughout development
|
||||
- Comprehensive metrics tracking (declarative ratio, component size)
|
||||
- Security-first approach with continuous vulnerability monitoring
|
||||
- Self-documenting with auto-generated deployment notes
|
||||
|
||||
**Documentation:**
|
||||
- Copilot Instructions: `.github/copilot-instructions.md`
|
||||
- Workflow Guide: `.github/workflows/README.md`
|
||||
- This Summary: `.github/COPILOT_SDLC_SUMMARY.md`
|
||||
|
||||
The workflows ensure that GitHub Copilot can assist developers at every stage, from initial planning through deployment and maintenance, while maintaining the project's architectural integrity and quality standards.
|
||||
|
||||
260
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
260
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,130 +1,130 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report this bug! Please fill out the form below to help us understand and fix the issue.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what went wrong...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: I expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Instead, I observed...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder is affected?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
description: How severe is this bug?
|
||||
options:
|
||||
- Critical (System crash, data loss)
|
||||
- High (Major feature broken)
|
||||
- Medium (Feature partially broken)
|
||||
- Low (Minor issue, workaround exists)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide your environment details
|
||||
value: |
|
||||
- OS: [e.g., Ubuntu 22.04, macOS 13.0, Windows 11]
|
||||
- Node Version: [e.g., 18.17.0]
|
||||
- Browser: [e.g., Chrome 120, Firefox 121]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant Logs/Screenshots
|
||||
description: Add any error logs, screenshots, or console output
|
||||
placeholder: |
|
||||
Paste logs here or drag and drop screenshots.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem
|
||||
placeholder: |
|
||||
- Does this happen consistently or intermittently?
|
||||
- Have you tried any workarounds?
|
||||
- Did this work in a previous version?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this is not a duplicate
|
||||
required: true
|
||||
- label: I have provided all required information above
|
||||
required: true
|
||||
- label: I have checked the documentation for relevant information
|
||||
required: false
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report this bug! Please fill out the form below to help us understand and fix the issue.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what went wrong...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: I expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Instead, I observed...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder is affected?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
description: How severe is this bug?
|
||||
options:
|
||||
- Critical (System crash, data loss)
|
||||
- High (Major feature broken)
|
||||
- Medium (Feature partially broken)
|
||||
- Low (Minor issue, workaround exists)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide your environment details
|
||||
value: |
|
||||
- OS: [e.g., Ubuntu 22.04, macOS 13.0, Windows 11]
|
||||
- Node Version: [e.g., 18.17.0]
|
||||
- Browser: [e.g., Chrome 120, Firefox 121]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant Logs/Screenshots
|
||||
description: Add any error logs, screenshots, or console output
|
||||
placeholder: |
|
||||
Paste logs here or drag and drop screenshots.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem
|
||||
placeholder: |
|
||||
- Does this happen consistently or intermittently?
|
||||
- Have you tried any workarounds?
|
||||
- Did this work in a previous version?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this is not a duplicate
|
||||
required: true
|
||||
- label: I have provided all required information above
|
||||
required: true
|
||||
- label: I have checked the documentation for relevant information
|
||||
required: false
|
||||
|
||||
22
.github/ISSUE_TEMPLATE/config.yml
vendored
22
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,11 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
about: Check our comprehensive documentation for guides and architecture details
|
||||
- name: 💬 Discussions
|
||||
url: https://github.com/johndoe6345789/metabuilder/discussions
|
||||
about: Ask questions and discuss ideas with the community
|
||||
- name: 🔒 Security Issues
|
||||
url: https://github.com/johndoe6345789/metabuilder/security/advisories/new
|
||||
about: Report security vulnerabilities privately
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
about: Check our comprehensive documentation for guides and architecture details
|
||||
- name: 💬 Discussions
|
||||
url: https://github.com/johndoe6345789/metabuilder/discussions
|
||||
about: Ask questions and discuss ideas with the community
|
||||
- name: 🔒 Security Issues
|
||||
url: https://github.com/johndoe6345789/metabuilder/security/advisories/new
|
||||
about: Report security vulnerabilities privately
|
||||
|
||||
316
.github/ISSUE_TEMPLATE/dbal_issue.yml
vendored
316
.github/ISSUE_TEMPLATE/dbal_issue.yml
vendored
@@ -1,158 +1,158 @@
|
||||
name: 🔧 DBAL Issue
|
||||
description: Report an issue with the Database Abstraction Layer (TypeScript or C++)
|
||||
title: "[DBAL]: "
|
||||
labels: ["dbal", "bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
DBAL is MetaBuilder's critical database abstraction layer with TypeScript (dev) and C++ (production) implementations.
|
||||
|
||||
- type: dropdown
|
||||
id: implementation
|
||||
attributes:
|
||||
label: DBAL Implementation
|
||||
description: Which DBAL implementation is affected?
|
||||
options:
|
||||
- TypeScript SDK (dbal/development/)
|
||||
- C++ Daemon (dbal/production/)
|
||||
- Both implementations
|
||||
- YAML Contracts (api/schema/)
|
||||
- Conformance Tests
|
||||
- Unknown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Describe the DBAL issue you're experiencing
|
||||
placeholder: The DBAL operation fails when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: operation
|
||||
attributes:
|
||||
label: Operation Type
|
||||
description: What type of operation is failing?
|
||||
options:
|
||||
- Entity Operations (CRUD)
|
||||
- Query Operations
|
||||
- Transaction Operations
|
||||
- Blob Storage
|
||||
- Key-Value Store
|
||||
- Tenant Management
|
||||
- Access Control
|
||||
- Connection Management
|
||||
- Type Generation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Code
|
||||
description: Provide code to reproduce the issue
|
||||
placeholder: |
|
||||
```typescript
|
||||
// Your code here
|
||||
const result = await dbalQuery({...})
|
||||
```
|
||||
render: typescript
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What should happen?
|
||||
placeholder: The operation should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happens?
|
||||
placeholder: Instead, I see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error
|
||||
attributes:
|
||||
label: Error Messages/Logs
|
||||
description: Include any error messages, stack traces, or logs
|
||||
render: shell
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
options:
|
||||
- Critical (Data corruption/loss)
|
||||
- High (Operation completely fails)
|
||||
- Medium (Operation partially works)
|
||||
- Low (Minor inconsistency)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment Details
|
||||
value: |
|
||||
- DBAL Version: [e.g., commit hash or version]
|
||||
- Node/C++ Version: [e.g., Node 18.17, gcc 11.3]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
- OS: [e.g., Ubuntu 22.04]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: parity
|
||||
attributes:
|
||||
label: Implementation Parity
|
||||
description: If both implementations exist, do they behave the same?
|
||||
options:
|
||||
- Both implementations fail
|
||||
- Only TypeScript fails
|
||||
- Only C++ fails
|
||||
- Different behavior between implementations
|
||||
- Haven't tested both
|
||||
- N/A (only one implementation exists)
|
||||
|
||||
- type: textarea
|
||||
id: conformance
|
||||
attributes:
|
||||
label: Conformance Test Status
|
||||
description: Do conformance tests pass for this operation?
|
||||
placeholder: |
|
||||
- Ran: python tools/conformance/run_all.py
|
||||
- Result: [Pass/Fail details]
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: YAML contract issues? Schema problems? Performance concerns?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have checked the YAML schema definitions in api/schema/
|
||||
required: true
|
||||
- label: I have verified this isn't a tenant isolation issue
|
||||
required: true
|
||||
- label: I have checked conformance test results if applicable
|
||||
required: false
|
||||
name: 🔧 DBAL Issue
|
||||
description: Report an issue with the Database Abstraction Layer (TypeScript or C++)
|
||||
title: "[DBAL]: "
|
||||
labels: ["dbal", "bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
DBAL is MetaBuilder's critical database abstraction layer with TypeScript (dev) and C++ (production) implementations.
|
||||
|
||||
- type: dropdown
|
||||
id: implementation
|
||||
attributes:
|
||||
label: DBAL Implementation
|
||||
description: Which DBAL implementation is affected?
|
||||
options:
|
||||
- TypeScript SDK (dbal/development/)
|
||||
- C++ Daemon (dbal/production/)
|
||||
- Both implementations
|
||||
- YAML Contracts (api/schema/)
|
||||
- Conformance Tests
|
||||
- Unknown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Describe the DBAL issue you're experiencing
|
||||
placeholder: The DBAL operation fails when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: operation
|
||||
attributes:
|
||||
label: Operation Type
|
||||
description: What type of operation is failing?
|
||||
options:
|
||||
- Entity Operations (CRUD)
|
||||
- Query Operations
|
||||
- Transaction Operations
|
||||
- Blob Storage
|
||||
- Key-Value Store
|
||||
- Tenant Management
|
||||
- Access Control
|
||||
- Connection Management
|
||||
- Type Generation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Code
|
||||
description: Provide code to reproduce the issue
|
||||
placeholder: |
|
||||
```typescript
|
||||
// Your code here
|
||||
const result = await dbalQuery({...})
|
||||
```
|
||||
render: typescript
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What should happen?
|
||||
placeholder: The operation should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happens?
|
||||
placeholder: Instead, I see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error
|
||||
attributes:
|
||||
label: Error Messages/Logs
|
||||
description: Include any error messages, stack traces, or logs
|
||||
render: shell
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
options:
|
||||
- Critical (Data corruption/loss)
|
||||
- High (Operation completely fails)
|
||||
- Medium (Operation partially works)
|
||||
- Low (Minor inconsistency)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment Details
|
||||
value: |
|
||||
- DBAL Version: [e.g., commit hash or version]
|
||||
- Node/C++ Version: [e.g., Node 18.17, gcc 11.3]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
- OS: [e.g., Ubuntu 22.04]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: parity
|
||||
attributes:
|
||||
label: Implementation Parity
|
||||
description: If both implementations exist, do they behave the same?
|
||||
options:
|
||||
- Both implementations fail
|
||||
- Only TypeScript fails
|
||||
- Only C++ fails
|
||||
- Different behavior between implementations
|
||||
- Haven't tested both
|
||||
- N/A (only one implementation exists)
|
||||
|
||||
- type: textarea
|
||||
id: conformance
|
||||
attributes:
|
||||
label: Conformance Test Status
|
||||
description: Do conformance tests pass for this operation?
|
||||
placeholder: |
|
||||
- Ran: python tools/conformance/run_all.py
|
||||
- Result: [Pass/Fail details]
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: YAML contract issues? Schema problems? Performance concerns?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have checked the YAML schema definitions in api/schema/
|
||||
required: true
|
||||
- label: I have verified this isn't a tenant isolation issue
|
||||
required: true
|
||||
- label: I have checked conformance test results if applicable
|
||||
required: false
|
||||
|
||||
230
.github/ISSUE_TEMPLATE/documentation.yml
vendored
230
.github/ISSUE_TEMPLATE/documentation.yml
vendored
@@ -1,115 +1,115 @@
|
||||
name: 📚 Documentation
|
||||
description: Report an issue with documentation or request documentation improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve MetaBuilder's documentation! Clear docs help everyone.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What kind of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect/outdated information
|
||||
- Unclear explanation
|
||||
- Broken links
|
||||
- Typo/grammar
|
||||
- Code example not working
|
||||
- Missing code example
|
||||
- Architecture documentation
|
||||
- API documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the documentation issue? (provide file path, URL, or section name)
|
||||
placeholder: |
|
||||
File: docs/architecture/packages.md
|
||||
Or URL: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
Or Section: "Getting Started > Database Setup"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: What's wrong with the current documentation?
|
||||
placeholder: The current documentation states... but it should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
The documentation should instead explain...
|
||||
Or: Add a section that covers...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Documentation Area
|
||||
description: Which area of MetaBuilder does this documentation cover?
|
||||
options:
|
||||
- Getting Started
|
||||
- Architecture
|
||||
- API Reference
|
||||
- Package System
|
||||
- DBAL
|
||||
- Permission System
|
||||
- Multi-Tenancy
|
||||
- Lua Scripting
|
||||
- Workflows
|
||||
- Database/Prisma
|
||||
- Testing
|
||||
- Deployment
|
||||
- Contributing
|
||||
- Security
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other relevant information
|
||||
placeholder: |
|
||||
- Screenshots of confusing sections
|
||||
- Related issues or PRs
|
||||
- Why this improvement is needed
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to help improve this documentation?
|
||||
options:
|
||||
- label: I am willing to submit a PR to fix/improve this documentation
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing issues for similar documentation requests
|
||||
required: true
|
||||
- label: I have verified the documentation issue still exists in the latest version
|
||||
required: true
|
||||
name: 📚 Documentation
|
||||
description: Report an issue with documentation or request documentation improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve MetaBuilder's documentation! Clear docs help everyone.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What kind of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect/outdated information
|
||||
- Unclear explanation
|
||||
- Broken links
|
||||
- Typo/grammar
|
||||
- Code example not working
|
||||
- Missing code example
|
||||
- Architecture documentation
|
||||
- API documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the documentation issue? (provide file path, URL, or section name)
|
||||
placeholder: |
|
||||
File: docs/architecture/packages.md
|
||||
Or URL: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
Or Section: "Getting Started > Database Setup"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: What's wrong with the current documentation?
|
||||
placeholder: The current documentation states... but it should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
The documentation should instead explain...
|
||||
Or: Add a section that covers...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Documentation Area
|
||||
description: Which area of MetaBuilder does this documentation cover?
|
||||
options:
|
||||
- Getting Started
|
||||
- Architecture
|
||||
- API Reference
|
||||
- Package System
|
||||
- DBAL
|
||||
- Permission System
|
||||
- Multi-Tenancy
|
||||
- Lua Scripting
|
||||
- Workflows
|
||||
- Database/Prisma
|
||||
- Testing
|
||||
- Deployment
|
||||
- Contributing
|
||||
- Security
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other relevant information
|
||||
placeholder: |
|
||||
- Screenshots of confusing sections
|
||||
- Related issues or PRs
|
||||
- Why this improvement is needed
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to help improve this documentation?
|
||||
options:
|
||||
- label: I am willing to submit a PR to fix/improve this documentation
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing issues for similar documentation requests
|
||||
required: true
|
||||
- label: I have verified the documentation issue still exists in the latest version
|
||||
required: true
|
||||
|
||||
268
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
268
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,134 +1,134 @@
|
||||
name: ✨ Feature Request
|
||||
description: Suggest a new feature or enhancement for MetaBuilder
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in improving MetaBuilder! Please describe your feature request in detail.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Is your feature request related to a problem? Describe what you're trying to achieve.
|
||||
placeholder: I'm frustrated when... / I need to be able to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see
|
||||
placeholder: I would like MetaBuilder to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Have you considered any alternative solutions or workarounds?
|
||||
placeholder: I've tried... but...
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder would this feature affect?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System (Levels 1-6)
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Developer Experience
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- High (Blocker for my use case)
|
||||
- Medium (Would be very helpful)
|
||||
- Low (Nice to have)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: user-level
|
||||
attributes:
|
||||
label: Target User Level
|
||||
description: Which permission level(s) would use this feature?
|
||||
multiple: true
|
||||
options:
|
||||
- Level 1 (Public)
|
||||
- Level 2 (User)
|
||||
- Level 3 (Moderator)
|
||||
- Level 4 (Admin)
|
||||
- Level 5 (God)
|
||||
- Level 6 (Supergod)
|
||||
- All levels
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Provide specific use cases or examples of how this feature would be used
|
||||
placeholder: |
|
||||
1. As a [user type], I want to [action] so that [benefit]
|
||||
2. When [scenario], this feature would help by [outcome]
|
||||
|
||||
- type: textarea
|
||||
id: technical
|
||||
attributes:
|
||||
label: Technical Considerations
|
||||
description: Any technical details, implementation ideas, or constraints?
|
||||
placeholder: |
|
||||
- This might require changes to...
|
||||
- Could be implemented using...
|
||||
- May affect performance of...
|
||||
|
||||
- type: textarea
|
||||
id: mockups
|
||||
attributes:
|
||||
label: Mockups/Examples
|
||||
description: Add any mockups, diagrams, or examples (drag and drop images or links)
|
||||
placeholder: Paste images or links here...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you be willing to help implement this feature?
|
||||
options:
|
||||
- label: I am willing to submit a PR for this feature
|
||||
required: false
|
||||
- label: I can help with testing this feature
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and discussions for similar requests
|
||||
required: true
|
||||
- label: This feature aligns with MetaBuilder's data-driven, multi-tenant architecture
|
||||
required: true
|
||||
- label: I have provided sufficient detail for others to understand the request
|
||||
required: true
|
||||
name: ✨ Feature Request
|
||||
description: Suggest a new feature or enhancement for MetaBuilder
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in improving MetaBuilder! Please describe your feature request in detail.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Is your feature request related to a problem? Describe what you're trying to achieve.
|
||||
placeholder: I'm frustrated when... / I need to be able to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see
|
||||
placeholder: I would like MetaBuilder to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Have you considered any alternative solutions or workarounds?
|
||||
placeholder: I've tried... but...
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder would this feature affect?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System (Levels 1-6)
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Developer Experience
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- High (Blocker for my use case)
|
||||
- Medium (Would be very helpful)
|
||||
- Low (Nice to have)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: user-level
|
||||
attributes:
|
||||
label: Target User Level
|
||||
description: Which permission level(s) would use this feature?
|
||||
multiple: true
|
||||
options:
|
||||
- Level 1 (Public)
|
||||
- Level 2 (User)
|
||||
- Level 3 (Moderator)
|
||||
- Level 4 (Admin)
|
||||
- Level 5 (God)
|
||||
- Level 6 (Supergod)
|
||||
- All levels
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Provide specific use cases or examples of how this feature would be used
|
||||
placeholder: |
|
||||
1. As a [user type], I want to [action] so that [benefit]
|
||||
2. When [scenario], this feature would help by [outcome]
|
||||
|
||||
- type: textarea
|
||||
id: technical
|
||||
attributes:
|
||||
label: Technical Considerations
|
||||
description: Any technical details, implementation ideas, or constraints?
|
||||
placeholder: |
|
||||
- This might require changes to...
|
||||
- Could be implemented using...
|
||||
- May affect performance of...
|
||||
|
||||
- type: textarea
|
||||
id: mockups
|
||||
attributes:
|
||||
label: Mockups/Examples
|
||||
description: Add any mockups, diagrams, or examples (drag and drop images or links)
|
||||
placeholder: Paste images or links here...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you be willing to help implement this feature?
|
||||
options:
|
||||
- label: I am willing to submit a PR for this feature
|
||||
required: false
|
||||
- label: I can help with testing this feature
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and discussions for similar requests
|
||||
required: true
|
||||
- label: This feature aligns with MetaBuilder's data-driven, multi-tenant architecture
|
||||
required: true
|
||||
- label: I have provided sufficient detail for others to understand the request
|
||||
required: true
|
||||
|
||||
328
.github/ISSUE_TEMPLATE/package_request.yml
vendored
328
.github/ISSUE_TEMPLATE/package_request.yml
vendored
@@ -1,164 +1,164 @@
|
||||
name: 📦 Package Request
|
||||
description: Request a new package for MetaBuilder's package system
|
||||
title: "[Package]: "
|
||||
labels: ["enhancement", "package", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
MetaBuilder's power comes from its data-driven package system. Request a new package here!
|
||||
|
||||
- type: input
|
||||
id: package-name
|
||||
attributes:
|
||||
label: Package Name
|
||||
description: Proposed name for the package (use snake_case)
|
||||
placeholder: e.g., blog_engine, task_manager, analytics_dashboard
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Package Description
|
||||
description: What functionality would this package provide?
|
||||
placeholder: This package would enable users to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: package-type
|
||||
attributes:
|
||||
label: Package Type
|
||||
description: What type of package is this?
|
||||
options:
|
||||
- UI Component/Widget
|
||||
- Feature Module
|
||||
- Integration
|
||||
- Tool/Utility
|
||||
- Template/Theme
|
||||
- Data Schema
|
||||
- Workflow
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: min-level
|
||||
attributes:
|
||||
label: Minimum Permission Level
|
||||
description: What's the minimum user level required to use this package?
|
||||
options:
|
||||
- Level 1 (Public - no auth required)
|
||||
- Level 2 (User - basic authentication)
|
||||
- Level 3 (Moderator - content moderation)
|
||||
- Level 4 (Admin - user management)
|
||||
- Level 5 (God - system configuration)
|
||||
- Level 6 (Supergod - full system control)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: features
|
||||
attributes:
|
||||
label: Key Features
|
||||
description: List the main features this package should include
|
||||
placeholder: |
|
||||
- Feature 1: Description
|
||||
- Feature 2: Description
|
||||
- Feature 3: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Describe scenarios where this package would be useful
|
||||
placeholder: |
|
||||
1. A [user type] needs to [action] in order to [goal]
|
||||
2. When [scenario], this package would help by [benefit]
|
||||
|
||||
- type: textarea
|
||||
id: components
|
||||
attributes:
|
||||
label: Proposed Components
|
||||
description: What UI components would this package include?
|
||||
placeholder: |
|
||||
- ComponentName1: Description
|
||||
- ComponentName2: Description
|
||||
|
||||
- type: textarea
|
||||
id: lua-scripts
|
||||
attributes:
|
||||
label: Lua Scripts Needed
|
||||
description: What Lua scripts would be required? (MetaBuilder is 95% JSON/Lua)
|
||||
placeholder: |
|
||||
- initialize.lua: Setup and configuration
|
||||
- validators.lua: Data validation
|
||||
- helpers.lua: Utility functions
|
||||
|
||||
- type: textarea
|
||||
id: schemas
|
||||
attributes:
|
||||
label: Database Schemas
|
||||
description: What database tables/models would be needed?
|
||||
placeholder: |
|
||||
- Model1 { field1, field2, ... }
|
||||
- Model2 { field1, field2, ... }
|
||||
|
||||
- type: textarea
|
||||
id: dependencies
|
||||
attributes:
|
||||
label: Package Dependencies
|
||||
description: Would this package depend on other packages?
|
||||
placeholder: |
|
||||
- @metabuilder/dashboard
|
||||
- @metabuilder/form_builder
|
||||
|
||||
- type: dropdown
|
||||
id: multi-tenant
|
||||
attributes:
|
||||
label: Multi-Tenant Support
|
||||
description: Does this package need to be tenant-aware?
|
||||
options:
|
||||
- "Yes - Requires tenant isolation"
|
||||
- "No - Can be global"
|
||||
- "Optional - Configurable"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: similar
|
||||
attributes:
|
||||
label: Similar Packages/Inspiration
|
||||
description: Are there similar packages in other systems or frameworks?
|
||||
placeholder: |
|
||||
- System X has a similar feature that...
|
||||
- This is inspired by...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
options:
|
||||
- label: I am willing to help develop this package
|
||||
required: false
|
||||
- label: I can provide Lua scripts for this package
|
||||
required: false
|
||||
- label: I can help with testing this package
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing packages to ensure this doesn't already exist
|
||||
required: true
|
||||
- label: This package aligns with MetaBuilder's data-driven architecture
|
||||
required: true
|
||||
- label: I have considered multi-tenant requirements
|
||||
required: true
|
||||
name: 📦 Package Request
|
||||
description: Request a new package for MetaBuilder's package system
|
||||
title: "[Package]: "
|
||||
labels: ["enhancement", "package", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
MetaBuilder's power comes from its data-driven package system. Request a new package here!
|
||||
|
||||
- type: input
|
||||
id: package-name
|
||||
attributes:
|
||||
label: Package Name
|
||||
description: Proposed name for the package (use snake_case)
|
||||
placeholder: e.g., blog_engine, task_manager, analytics_dashboard
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Package Description
|
||||
description: What functionality would this package provide?
|
||||
placeholder: This package would enable users to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: package-type
|
||||
attributes:
|
||||
label: Package Type
|
||||
description: What type of package is this?
|
||||
options:
|
||||
- UI Component/Widget
|
||||
- Feature Module
|
||||
- Integration
|
||||
- Tool/Utility
|
||||
- Template/Theme
|
||||
- Data Schema
|
||||
- Workflow
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: min-level
|
||||
attributes:
|
||||
label: Minimum Permission Level
|
||||
description: What's the minimum user level required to use this package?
|
||||
options:
|
||||
- Level 1 (Public - no auth required)
|
||||
- Level 2 (User - basic authentication)
|
||||
- Level 3 (Moderator - content moderation)
|
||||
- Level 4 (Admin - user management)
|
||||
- Level 5 (God - system configuration)
|
||||
- Level 6 (Supergod - full system control)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: features
|
||||
attributes:
|
||||
label: Key Features
|
||||
description: List the main features this package should include
|
||||
placeholder: |
|
||||
- Feature 1: Description
|
||||
- Feature 2: Description
|
||||
- Feature 3: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Describe scenarios where this package would be useful
|
||||
placeholder: |
|
||||
1. A [user type] needs to [action] in order to [goal]
|
||||
2. When [scenario], this package would help by [benefit]
|
||||
|
||||
- type: textarea
|
||||
id: components
|
||||
attributes:
|
||||
label: Proposed Components
|
||||
description: What UI components would this package include?
|
||||
placeholder: |
|
||||
- ComponentName1: Description
|
||||
- ComponentName2: Description
|
||||
|
||||
- type: textarea
|
||||
id: lua-scripts
|
||||
attributes:
|
||||
label: Lua Scripts Needed
|
||||
description: What Lua scripts would be required? (MetaBuilder is 95% JSON/Lua)
|
||||
placeholder: |
|
||||
- initialize.lua: Setup and configuration
|
||||
- validators.lua: Data validation
|
||||
- helpers.lua: Utility functions
|
||||
|
||||
- type: textarea
|
||||
id: schemas
|
||||
attributes:
|
||||
label: Database Schemas
|
||||
description: What database tables/models would be needed?
|
||||
placeholder: |
|
||||
- Model1 { field1, field2, ... }
|
||||
- Model2 { field1, field2, ... }
|
||||
|
||||
- type: textarea
|
||||
id: dependencies
|
||||
attributes:
|
||||
label: Package Dependencies
|
||||
description: Would this package depend on other packages?
|
||||
placeholder: |
|
||||
- @metabuilder/dashboard
|
||||
- @metabuilder/form_builder
|
||||
|
||||
- type: dropdown
|
||||
id: multi-tenant
|
||||
attributes:
|
||||
label: Multi-Tenant Support
|
||||
description: Does this package need to be tenant-aware?
|
||||
options:
|
||||
- "Yes - Requires tenant isolation"
|
||||
- "No - Can be global"
|
||||
- "Optional - Configurable"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: similar
|
||||
attributes:
|
||||
label: Similar Packages/Inspiration
|
||||
description: Are there similar packages in other systems or frameworks?
|
||||
placeholder: |
|
||||
- System X has a similar feature that...
|
||||
- This is inspired by...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
options:
|
||||
- label: I am willing to help develop this package
|
||||
required: false
|
||||
- label: I can provide Lua scripts for this package
|
||||
required: false
|
||||
- label: I can help with testing this package
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing packages to ensure this doesn't already exist
|
||||
required: true
|
||||
- label: This package aligns with MetaBuilder's data-driven architecture
|
||||
required: true
|
||||
- label: I have considered multi-tenant requirements
|
||||
required: true
|
||||
|
||||
486
.github/PULL_REQUEST_TEMPLATE.md
vendored
486
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,243 +1,243 @@
|
||||
## Description
|
||||
|
||||
<!-- Provide a clear and concise description of your changes -->
|
||||
|
||||
## Related Issue
|
||||
|
||||
<!-- Link to the issue this PR addresses -->
|
||||
Fixes #<!-- issue number -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
<!-- Mark the relevant option with an "x" -->
|
||||
|
||||
- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)
|
||||
- [ ] ✨ New feature (non-breaking change that adds functionality)
|
||||
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] 📚 Documentation update
|
||||
- [ ] 🎨 UI/UX improvement
|
||||
- [ ] ♻️ Code refactoring (no functional changes)
|
||||
- [ ] ⚡ Performance improvement
|
||||
- [ ] ✅ Test additions or updates
|
||||
- [ ] 🔧 Configuration/tooling change
|
||||
- [ ] 📦 Package system change
|
||||
- [ ] 🔒 Security fix
|
||||
|
||||
## Component/Area Affected
|
||||
|
||||
<!-- Mark all that apply with an "x" -->
|
||||
|
||||
- [ ] Frontend (Next.js UI)
|
||||
- [ ] Backend (API/Auth)
|
||||
- [ ] Database (Prisma/Schema)
|
||||
- [ ] DBAL (TypeScript/C++)
|
||||
- [ ] Package System
|
||||
- [ ] Lua Scripting
|
||||
- [ ] Multi-Tenant System
|
||||
- [ ] Permission System (Levels 1-6)
|
||||
- [ ] Workflows
|
||||
- [ ] Documentation
|
||||
- [ ] Testing
|
||||
- [ ] CI/CD
|
||||
- [ ] Other: <!-- specify -->
|
||||
|
||||
## Changes Made
|
||||
|
||||
<!-- Provide a detailed list of changes -->
|
||||
|
||||
### Code Changes
|
||||
-
|
||||
-
|
||||
|
||||
### Database Changes
|
||||
- [ ] Schema changes (Prisma migrations)
|
||||
- [ ] Seed data updates
|
||||
- [ ] DBAL contract changes (YAML)
|
||||
|
||||
### Configuration Changes
|
||||
- [ ] Environment variables
|
||||
- [ ] Build configuration
|
||||
- [ ] Package dependencies
|
||||
|
||||
## Testing
|
||||
|
||||
<!-- Describe the tests you ran and their results -->
|
||||
|
||||
### Test Coverage
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Integration tests added/updated
|
||||
- [ ] E2E tests added/updated
|
||||
- [ ] No tests needed (documentation, config, etc.)
|
||||
|
||||
### Test Commands Run
|
||||
```bash
|
||||
# Example:
|
||||
# npm run lint
|
||||
# npm run typecheck
|
||||
# npm run test:unit -- --run
|
||||
# npm run test:e2e
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
<!-- Describe manual testing performed -->
|
||||
- [ ] Tested locally
|
||||
- [ ] Tested in development environment
|
||||
- [ ] Tested with different user permission levels
|
||||
- [ ] Tested multi-tenant scenarios
|
||||
|
||||
## Screenshots/Recordings
|
||||
|
||||
<!-- If applicable, add screenshots or recordings to demonstrate UI changes -->
|
||||
|
||||
### Before
|
||||
<!-- Screenshot or description of before state -->
|
||||
|
||||
### After
|
||||
<!-- Screenshot or description of after state -->
|
||||
|
||||
## Architecture & Design Decisions
|
||||
|
||||
<!-- Document any architectural or design decisions made -->
|
||||
|
||||
### Data-Driven Approach
|
||||
- [ ] Changes follow MetaBuilder's data-driven (JSON/Lua) architecture
|
||||
- [ ] Declarative components used instead of hardcoded JSX where applicable
|
||||
- [ ] DBAL used for database operations (not raw Prisma)
|
||||
|
||||
### Multi-Tenancy
|
||||
- [ ] All queries include `tenantId` filtering
|
||||
- [ ] Tenant isolation verified
|
||||
- [ ] N/A - No database queries
|
||||
|
||||
### Permission System
|
||||
- [ ] Permission checks implemented at correct levels
|
||||
- [ ] AuthGate or canAccessLevel used where needed
|
||||
- [ ] N/A - No permission-sensitive features
|
||||
|
||||
### Package System
|
||||
- [ ] Package metadata follows correct structure (metadata.json, components.json)
|
||||
- [ ] Package uses snake_case naming and semver versioning
|
||||
- [ ] Dependencies declared in package metadata
|
||||
- [ ] N/A - No package changes
|
||||
|
||||
### Security
|
||||
- [ ] Input validation implemented
|
||||
- [ ] No XSS vulnerabilities introduced
|
||||
- [ ] No SQL injection vulnerabilities
|
||||
- [ ] Passwords hashed with SHA-512 (if applicable)
|
||||
- [ ] Lua sandbox restrictions maintained (if applicable)
|
||||
- [ ] No secrets committed to code
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
<!-- If this PR introduces breaking changes, describe them and migration steps -->
|
||||
|
||||
**Breaking Changes:** Yes / No
|
||||
|
||||
<!-- If yes, describe:
|
||||
- What breaks
|
||||
- Why the change was necessary
|
||||
- How to migrate existing code/data
|
||||
- Impact on different user levels
|
||||
-->
|
||||
|
||||
## Migration Steps
|
||||
|
||||
<!-- If database migrations or data migrations are needed -->
|
||||
|
||||
```bash
|
||||
# Commands needed to migrate:
|
||||
# npm run db:generate
|
||||
# npm run db:migrate
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
<!-- Mark all that apply -->
|
||||
|
||||
- [ ] README.md updated
|
||||
- [ ] API documentation updated
|
||||
- [ ] Architecture docs updated (docs/architecture/)
|
||||
- [ ] Code comments added/updated
|
||||
- [ ] Migration guide created (if breaking change)
|
||||
- [ ] No documentation needed
|
||||
|
||||
## Pre-Submission Checklist
|
||||
|
||||
<!-- Verify all items before submitting -->
|
||||
|
||||
### Code Quality
|
||||
- [ ] Code follows project conventions (one lambda per file, MUI not Radix/Tailwind)
|
||||
- [ ] ESLint passes (`npm run lint`)
|
||||
- [ ] TypeScript compiles (`npm run typecheck`)
|
||||
- [ ] No console errors or warnings
|
||||
- [ ] Code is DRY (Don't Repeat Yourself)
|
||||
|
||||
### Testing & Verification
|
||||
- [ ] All tests pass (`npm run test:unit -- --run`)
|
||||
- [ ] Test coverage for new code meets standards
|
||||
- [ ] E2E tests pass (if applicable)
|
||||
- [ ] Manual testing completed
|
||||
- [ ] Tested across different browsers (if UI change)
|
||||
|
||||
### Database & Schema
|
||||
- [ ] Prisma schema validated (`npx prisma validate`)
|
||||
- [ ] Database migrations tested
|
||||
- [ ] DBAL conformance tests pass (if DBAL changes)
|
||||
- [ ] N/A - No database changes
|
||||
|
||||
### Security
|
||||
- [ ] Security vulnerabilities checked
|
||||
- [ ] No sensitive data in commits
|
||||
- [ ] Input validation implemented
|
||||
- [ ] CSRF/XSS protections in place (if applicable)
|
||||
|
||||
### MetaBuilder-Specific
|
||||
- [ ] Changes align with data-driven architecture principles
|
||||
- [ ] Multi-tenant safety verified (tenantId filtering)
|
||||
- [ ] Permission checks implemented correctly
|
||||
- [ ] DBAL used instead of raw Prisma (where applicable)
|
||||
- [ ] Generic components used where possible (RenderComponent)
|
||||
|
||||
### Review
|
||||
- [ ] Self-reviewed code changes
|
||||
- [ ] Added TODO comments for deferred work (if any)
|
||||
- [ ] Commit messages are clear and descriptive
|
||||
- [ ] PR title is descriptive
|
||||
- [ ] No unrelated changes included
|
||||
|
||||
## Additional Notes
|
||||
|
||||
<!-- Any additional information, context, or concerns -->
|
||||
|
||||
## Deployment Considerations
|
||||
|
||||
<!-- Notes for deployment -->
|
||||
|
||||
- [ ] No special deployment steps needed
|
||||
- [ ] Requires environment variable changes
|
||||
- [ ] Requires database migration
|
||||
- [ ] Requires cache invalidation
|
||||
- [ ] Requires server restart
|
||||
- [ ] Other: <!-- specify -->
|
||||
|
||||
## Reviewer Notes
|
||||
|
||||
<!-- Specific areas where you'd like reviewer focus -->
|
||||
|
||||
**Focus Areas:**
|
||||
-
|
||||
-
|
||||
|
||||
**Questions for Reviewers:**
|
||||
-
|
||||
-
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
By submitting this PR, I confirm that:
|
||||
- My contribution follows the project's code of conduct
|
||||
- I have the right to submit this code
|
||||
- I understand this will be released under the project's license
|
||||
-->
|
||||
## Description
|
||||
|
||||
<!-- Provide a clear and concise description of your changes -->
|
||||
|
||||
## Related Issue
|
||||
|
||||
<!-- Link to the issue this PR addresses -->
|
||||
Fixes #<!-- issue number -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
<!-- Mark the relevant option with an "x" -->
|
||||
|
||||
- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)
|
||||
- [ ] ✨ New feature (non-breaking change that adds functionality)
|
||||
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] 📚 Documentation update
|
||||
- [ ] 🎨 UI/UX improvement
|
||||
- [ ] ♻️ Code refactoring (no functional changes)
|
||||
- [ ] ⚡ Performance improvement
|
||||
- [ ] ✅ Test additions or updates
|
||||
- [ ] 🔧 Configuration/tooling change
|
||||
- [ ] 📦 Package system change
|
||||
- [ ] 🔒 Security fix
|
||||
|
||||
## Component/Area Affected
|
||||
|
||||
<!-- Mark all that apply with an "x" -->
|
||||
|
||||
- [ ] Frontend (Next.js UI)
|
||||
- [ ] Backend (API/Auth)
|
||||
- [ ] Database (Prisma/Schema)
|
||||
- [ ] DBAL (TypeScript/C++)
|
||||
- [ ] Package System
|
||||
- [ ] Lua Scripting
|
||||
- [ ] Multi-Tenant System
|
||||
- [ ] Permission System (Levels 1-6)
|
||||
- [ ] Workflows
|
||||
- [ ] Documentation
|
||||
- [ ] Testing
|
||||
- [ ] CI/CD
|
||||
- [ ] Other: <!-- specify -->
|
||||
|
||||
## Changes Made
|
||||
|
||||
<!-- Provide a detailed list of changes -->
|
||||
|
||||
### Code Changes
|
||||
-
|
||||
-
|
||||
|
||||
### Database Changes
|
||||
- [ ] Schema changes (Prisma migrations)
|
||||
- [ ] Seed data updates
|
||||
- [ ] DBAL contract changes (YAML)
|
||||
|
||||
### Configuration Changes
|
||||
- [ ] Environment variables
|
||||
- [ ] Build configuration
|
||||
- [ ] Package dependencies
|
||||
|
||||
## Testing
|
||||
|
||||
<!-- Describe the tests you ran and their results -->
|
||||
|
||||
### Test Coverage
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Integration tests added/updated
|
||||
- [ ] E2E tests added/updated
|
||||
- [ ] No tests needed (documentation, config, etc.)
|
||||
|
||||
### Test Commands Run
|
||||
```bash
|
||||
# Example:
|
||||
# npm run lint
|
||||
# npm run typecheck
|
||||
# npm run test:unit -- --run
|
||||
# npm run test:e2e
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
<!-- Describe manual testing performed -->
|
||||
- [ ] Tested locally
|
||||
- [ ] Tested in development environment
|
||||
- [ ] Tested with different user permission levels
|
||||
- [ ] Tested multi-tenant scenarios
|
||||
|
||||
## Screenshots/Recordings
|
||||
|
||||
<!-- If applicable, add screenshots or recordings to demonstrate UI changes -->
|
||||
|
||||
### Before
|
||||
<!-- Screenshot or description of before state -->
|
||||
|
||||
### After
|
||||
<!-- Screenshot or description of after state -->
|
||||
|
||||
## Architecture & Design Decisions
|
||||
|
||||
<!-- Document any architectural or design decisions made -->
|
||||
|
||||
### Data-Driven Approach
|
||||
- [ ] Changes follow MetaBuilder's data-driven (JSON/Lua) architecture
|
||||
- [ ] Declarative components used instead of hardcoded JSX where applicable
|
||||
- [ ] DBAL used for database operations (not raw Prisma)
|
||||
|
||||
### Multi-Tenancy
|
||||
- [ ] All queries include `tenantId` filtering
|
||||
- [ ] Tenant isolation verified
|
||||
- [ ] N/A - No database queries
|
||||
|
||||
### Permission System
|
||||
- [ ] Permission checks implemented at correct levels
|
||||
- [ ] AuthGate or canAccessLevel used where needed
|
||||
- [ ] N/A - No permission-sensitive features
|
||||
|
||||
### Package System
|
||||
- [ ] Package metadata follows correct structure (metadata.json, components.json)
|
||||
- [ ] Package uses snake_case naming and semver versioning
|
||||
- [ ] Dependencies declared in package metadata
|
||||
- [ ] N/A - No package changes
|
||||
|
||||
### Security
|
||||
- [ ] Input validation implemented
|
||||
- [ ] No XSS vulnerabilities introduced
|
||||
- [ ] No SQL injection vulnerabilities
|
||||
- [ ] Passwords hashed with SHA-512 (if applicable)
|
||||
- [ ] Lua sandbox restrictions maintained (if applicable)
|
||||
- [ ] No secrets committed to code
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
<!-- If this PR introduces breaking changes, describe them and migration steps -->
|
||||
|
||||
**Breaking Changes:** Yes / No
|
||||
|
||||
<!-- If yes, describe:
|
||||
- What breaks
|
||||
- Why the change was necessary
|
||||
- How to migrate existing code/data
|
||||
- Impact on different user levels
|
||||
-->
|
||||
|
||||
## Migration Steps
|
||||
|
||||
<!-- If database migrations or data migrations are needed -->
|
||||
|
||||
```bash
|
||||
# Commands needed to migrate:
|
||||
# npm run db:generate
|
||||
# npm run db:migrate
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
<!-- Mark all that apply -->
|
||||
|
||||
- [ ] README.md updated
|
||||
- [ ] API documentation updated
|
||||
- [ ] Architecture docs updated (docs/architecture/)
|
||||
- [ ] Code comments added/updated
|
||||
- [ ] Migration guide created (if breaking change)
|
||||
- [ ] No documentation needed
|
||||
|
||||
## Pre-Submission Checklist
|
||||
|
||||
<!-- Verify all items before submitting -->
|
||||
|
||||
### Code Quality
|
||||
- [ ] Code follows project conventions (one lambda per file, MUI not Radix/Tailwind)
|
||||
- [ ] ESLint passes (`npm run lint`)
|
||||
- [ ] TypeScript compiles (`npm run typecheck`)
|
||||
- [ ] No console errors or warnings
|
||||
- [ ] Code is DRY (Don't Repeat Yourself)
|
||||
|
||||
### Testing & Verification
|
||||
- [ ] All tests pass (`npm run test:unit -- --run`)
|
||||
- [ ] Test coverage for new code meets standards
|
||||
- [ ] E2E tests pass (if applicable)
|
||||
- [ ] Manual testing completed
|
||||
- [ ] Tested across different browsers (if UI change)
|
||||
|
||||
### Database & Schema
|
||||
- [ ] Prisma schema validated (`npx prisma validate`)
|
||||
- [ ] Database migrations tested
|
||||
- [ ] DBAL conformance tests pass (if DBAL changes)
|
||||
- [ ] N/A - No database changes
|
||||
|
||||
### Security
|
||||
- [ ] Security vulnerabilities checked
|
||||
- [ ] No sensitive data in commits
|
||||
- [ ] Input validation implemented
|
||||
- [ ] CSRF/XSS protections in place (if applicable)
|
||||
|
||||
### MetaBuilder-Specific
|
||||
- [ ] Changes align with data-driven architecture principles
|
||||
- [ ] Multi-tenant safety verified (tenantId filtering)
|
||||
- [ ] Permission checks implemented correctly
|
||||
- [ ] DBAL used instead of raw Prisma (where applicable)
|
||||
- [ ] Generic components used where possible (RenderComponent)
|
||||
|
||||
### Review
|
||||
- [ ] Self-reviewed code changes
|
||||
- [ ] Added TODO comments for deferred work (if any)
|
||||
- [ ] Commit messages are clear and descriptive
|
||||
- [ ] PR title is descriptive
|
||||
- [ ] No unrelated changes included
|
||||
|
||||
## Additional Notes
|
||||
|
||||
<!-- Any additional information, context, or concerns -->
|
||||
|
||||
## Deployment Considerations
|
||||
|
||||
<!-- Notes for deployment -->
|
||||
|
||||
- [ ] No special deployment steps needed
|
||||
- [ ] Requires environment variable changes
|
||||
- [ ] Requires database migration
|
||||
- [ ] Requires cache invalidation
|
||||
- [ ] Requires server restart
|
||||
- [ ] Other: <!-- specify -->
|
||||
|
||||
## Reviewer Notes
|
||||
|
||||
<!-- Specific areas where you'd like reviewer focus -->
|
||||
|
||||
**Focus Areas:**
|
||||
-
|
||||
-
|
||||
|
||||
**Questions for Reviewers:**
|
||||
-
|
||||
-
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
By submitting this PR, I confirm that:
|
||||
- My contribution follows the project's code of conduct
|
||||
- I have the right to submit this code
|
||||
- I understand this will be released under the project's license
|
||||
-->
|
||||
|
||||
686
.github/TEMPLATES.md
vendored
686
.github/TEMPLATES.md
vendored
@@ -1,343 +1,343 @@
|
||||
# Issue and Pull Request Templates
|
||||
|
||||
This document describes the issue and PR templates available for MetaBuilder and how to use them effectively.
|
||||
|
||||
## Overview
|
||||
|
||||
MetaBuilder uses structured templates to ensure consistent, high-quality issues and pull requests. These templates are specifically designed for MetaBuilder's data-driven, multi-tenant architecture.
|
||||
|
||||
## Issue Templates
|
||||
|
||||
### Available Templates
|
||||
|
||||
#### 🐛 Bug Report (`bug_report.yml`)
|
||||
Use this template to report bugs or unexpected behavior.
|
||||
|
||||
**Key Features:**
|
||||
- Environment details capture (OS, Node version, browser, database)
|
||||
- Severity levels (Critical, High, Medium, Low)
|
||||
- Component categorization
|
||||
- Reproducible steps
|
||||
- Pre-submission checklist
|
||||
|
||||
**Best For:**
|
||||
- Application crashes or errors
|
||||
- Features not working as expected
|
||||
- Performance issues
|
||||
- UI/UX bugs
|
||||
|
||||
#### ✨ Feature Request (`feature_request.yml`)
|
||||
Request new features or enhancements aligned with MetaBuilder's architecture.
|
||||
|
||||
**Key Features:**
|
||||
- Problem statement and solution proposal
|
||||
- Target user permission levels (Level 1-6)
|
||||
- Priority assessment
|
||||
- Use case descriptions
|
||||
- Technical considerations
|
||||
- Contribution willingness
|
||||
|
||||
**Best For:**
|
||||
- New feature ideas
|
||||
- Improvements to existing features
|
||||
- API enhancements
|
||||
- User experience improvements
|
||||
|
||||
#### 📚 Documentation (`documentation.yml`)
|
||||
Report documentation issues or request improvements.
|
||||
|
||||
**Key Features:**
|
||||
- Documentation type categorization
|
||||
- Location/path specification
|
||||
- Suggested improvements
|
||||
- Documentation area targeting
|
||||
|
||||
**Best For:**
|
||||
- Missing documentation
|
||||
- Outdated information
|
||||
- Unclear explanations
|
||||
- Broken links or typos
|
||||
- Missing code examples
|
||||
|
||||
#### 📦 Package Request (`package_request.yml`)
|
||||
Request new packages for MetaBuilder's package system.
|
||||
|
||||
**Key Features:**
|
||||
- Package naming (snake_case convention)
|
||||
- Package type selection
|
||||
- Minimum permission level
|
||||
- Component and Lua script planning
|
||||
- Database schema requirements
|
||||
- Multi-tenant consideration
|
||||
|
||||
**Best For:**
|
||||
- New package ideas
|
||||
- Package integrations
|
||||
- Package improvements
|
||||
- Community packages
|
||||
|
||||
**Special Considerations:**
|
||||
- Package names must use snake_case
|
||||
- Must specify multi-tenant requirements
|
||||
- Should include Lua script needs (MetaBuilder is 95% JSON/Lua)
|
||||
- Must declare dependencies
|
||||
|
||||
#### 🔧 DBAL Issue (`dbal_issue.yml`)
|
||||
Report issues with the Database Abstraction Layer.
|
||||
|
||||
**Key Features:**
|
||||
- Implementation selection (TypeScript/C++)
|
||||
- Operation type categorization
|
||||
- Conformance test status
|
||||
- Implementation parity checks
|
||||
- Severity levels
|
||||
|
||||
**Best For:**
|
||||
- DBAL TypeScript SDK issues (`dbal/ts/`)
|
||||
- DBAL C++ daemon issues (`dbal/production/`)
|
||||
- YAML contract problems (`api/schema/`)
|
||||
- Conformance test failures
|
||||
- Implementation inconsistencies
|
||||
|
||||
**Special Considerations:**
|
||||
- Check YAML schema definitions first
|
||||
- Run conformance tests if applicable
|
||||
- Verify tenant isolation
|
||||
- Note if both implementations behave differently
|
||||
|
||||
### Template Configuration (`config.yml`)
|
||||
|
||||
The config file provides:
|
||||
- Documentation links
|
||||
- Community discussion links
|
||||
- Private security reporting
|
||||
- Disables blank issues to ensure structure
|
||||
|
||||
## Pull Request Template
|
||||
|
||||
### Structure
|
||||
|
||||
The PR template (`PULL_REQUEST_TEMPLATE.md`) includes comprehensive sections:
|
||||
|
||||
#### 1. Basic Information
|
||||
- Description of changes
|
||||
- Related issue linking
|
||||
- Type of change
|
||||
- Component/area affected
|
||||
|
||||
#### 2. Changes Made
|
||||
- Detailed list of code changes
|
||||
- Database/schema changes
|
||||
- Configuration changes
|
||||
|
||||
#### 3. Testing
|
||||
- Test coverage (unit, integration, E2E)
|
||||
- Manual testing verification
|
||||
- Permission level testing
|
||||
- Multi-tenant scenario testing
|
||||
|
||||
#### 4. Architecture & Design Decisions
|
||||
|
||||
**Data-Driven Approach:**
|
||||
- Verify JSON/Lua architecture alignment
|
||||
- Use of declarative components
|
||||
- DBAL usage for database operations
|
||||
|
||||
**Multi-Tenancy:**
|
||||
- TenantId filtering verification
|
||||
- Tenant isolation checks
|
||||
|
||||
**Permission System:**
|
||||
- Permission checks at correct levels
|
||||
- AuthGate/canAccessLevel usage
|
||||
|
||||
**Package System:**
|
||||
- Metadata structure compliance
|
||||
- Naming conventions (snake_case, semver)
|
||||
- Dependency declarations
|
||||
|
||||
**Security:**
|
||||
- Input validation
|
||||
- XSS/SQL injection checks
|
||||
- Password hashing (SHA-512)
|
||||
- Lua sandbox restrictions
|
||||
- No secrets in code
|
||||
|
||||
#### 5. Breaking Changes
|
||||
- Migration steps
|
||||
- Impact assessment
|
||||
- Upgrade guide
|
||||
|
||||
#### 6. Documentation
|
||||
- README updates
|
||||
- API documentation
|
||||
- Architecture docs
|
||||
- Migration guides
|
||||
|
||||
#### 7. Pre-Submission Checklist
|
||||
|
||||
**Code Quality:**
|
||||
- Follows conventions (one lambda per file)
|
||||
- Uses MUI (not Radix/Tailwind)
|
||||
- ESLint passes
|
||||
- TypeScript compiles
|
||||
|
||||
**Testing:**
|
||||
- All tests pass
|
||||
- Test coverage adequate
|
||||
- E2E tests pass (if applicable)
|
||||
- Cross-browser testing (if UI)
|
||||
|
||||
**Database & Schema:**
|
||||
- Prisma schema validated
|
||||
- Migrations tested
|
||||
- DBAL conformance tests pass
|
||||
|
||||
**Security:**
|
||||
- Vulnerabilities checked
|
||||
- Input validation implemented
|
||||
- No sensitive data committed
|
||||
|
||||
**MetaBuilder-Specific:**
|
||||
- Data-driven architecture alignment
|
||||
- Multi-tenant safety verified
|
||||
- Permission checks correct
|
||||
- DBAL used (not raw Prisma)
|
||||
- Generic components where possible
|
||||
|
||||
#### 8. Additional Sections
|
||||
- Deployment considerations
|
||||
- Reviewer notes
|
||||
- Focus areas for review
|
||||
|
||||
## Using the Templates
|
||||
|
||||
### Creating an Issue
|
||||
|
||||
1. Go to the [Issues page](https://github.com/johndoe6345789/metabuilder/issues)
|
||||
2. Click "New issue"
|
||||
3. Select the appropriate template
|
||||
4. Fill in all required fields (marked with red asterisk)
|
||||
5. Complete the pre-submission checklist
|
||||
6. Submit the issue
|
||||
|
||||
### Creating a Pull Request
|
||||
|
||||
1. Push your branch to GitHub
|
||||
2. Navigate to the repository
|
||||
3. Click "Pull requests" → "New pull request"
|
||||
4. Select your branch
|
||||
5. The PR template will auto-populate
|
||||
6. Fill in all sections thoroughly
|
||||
7. Mark checkboxes in the pre-submission checklist
|
||||
8. Submit the PR
|
||||
|
||||
### Template Tips
|
||||
|
||||
**For Issues:**
|
||||
- Be specific and detailed
|
||||
- Include reproduction steps for bugs
|
||||
- Provide environment details
|
||||
- Search for duplicates first
|
||||
- Check documentation before submitting
|
||||
|
||||
**For PRs:**
|
||||
- Link related issues
|
||||
- Include screenshots for UI changes
|
||||
- Document breaking changes clearly
|
||||
- Run all tests before submitting
|
||||
- Complete the entire checklist
|
||||
- Focus on minimal, surgical changes
|
||||
|
||||
## MetaBuilder-Specific Guidelines
|
||||
|
||||
### Data-Driven Architecture
|
||||
MetaBuilder is 95% JSON/Lua, not TypeScript. When contributing:
|
||||
- Prefer JSON/Lua configuration over hardcoded TS
|
||||
- Use `RenderComponent` for declarative UI
|
||||
- Add Lua scripts to `packages/*/seed/scripts/`
|
||||
- Keep TypeScript as adapters/wrappers
|
||||
|
||||
### Multi-Tenancy
|
||||
All contributions must respect tenant isolation:
|
||||
- Include `tenantId` in all queries
|
||||
- Use `Database` class methods, not raw Prisma
|
||||
- Test with multiple tenants
|
||||
- Document tenant-specific behavior
|
||||
|
||||
### Permission System (Levels 1-6)
|
||||
- Level 1: Public (no auth)
|
||||
- Level 2: User (basic auth)
|
||||
- Level 3: Moderator (content moderation)
|
||||
- Level 4: Admin (user management)
|
||||
- Level 5: God (system config, packages)
|
||||
- Level 6: Supergod (full system control)
|
||||
|
||||
When adding features, specify the minimum required level and use `canAccessLevel()` checks.
|
||||
|
||||
### Package System
|
||||
Packages follow strict conventions:
|
||||
- Name: `snake_case` (e.g., `blog_engine`)
|
||||
- Version: Semver (e.g., `1.2.3`)
|
||||
- Structure: `packages/{name}/seed/` with `metadata.json`, `components.json`
|
||||
- Lua scripts in `packages/{name}/seed/scripts/`
|
||||
- Optional React components in `packages/{name}/src/`
|
||||
|
||||
### DBAL (Database Abstraction Layer)
|
||||
- TypeScript implementation: `dbal/ts/` (development)
|
||||
- C++ implementation: `dbal/production/` (production)
|
||||
- YAML contracts: `api/schema/` (source of truth)
|
||||
- Always update YAML first
|
||||
- Run conformance tests: `python tools/conformance/run_all.py`
|
||||
- Ensure both implementations behave identically
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Issue Reporting
|
||||
1. **Search first**: Check if the issue already exists
|
||||
2. **Be specific**: Provide exact steps and details
|
||||
3. **Be respectful**: Follow the code of conduct
|
||||
4. **Be patient**: Maintainers will respond when available
|
||||
5. **Follow up**: Provide additional info if requested
|
||||
|
||||
### Pull Requests
|
||||
1. **Small changes**: Keep PRs focused and minimal
|
||||
2. **Test thoroughly**: Run all tests and linters
|
||||
3. **Document well**: Update docs with changes
|
||||
4. **Follow conventions**: Match existing code style
|
||||
5. **Respond quickly**: Address review feedback promptly
|
||||
|
||||
### Security
|
||||
- **Never commit secrets**: No API keys, passwords, tokens
|
||||
- **Report privately**: Use GitHub Security Advisories for vulnerabilities
|
||||
- **Hash passwords**: Always use SHA-512 via `password-utils.ts`
|
||||
- **Validate input**: Never trust user input
|
||||
- **Sandbox Lua**: Maintain Lua script restrictions
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you have questions about the templates or contribution process:
|
||||
|
||||
1. **Documentation**: Check [docs/](../docs/) for guides
|
||||
2. **Discussions**: Ask in [GitHub Discussions](https://github.com/johndoe6345789/metabuilder/discussions)
|
||||
3. **Examples**: Look at existing issues and PRs
|
||||
4. **Workflow Guide**: See `.github/prompts/0-kickstart.md`
|
||||
|
||||
## Template Maintenance
|
||||
|
||||
These templates are living documents. If you find:
|
||||
- Missing fields or options
|
||||
- Unclear instructions
|
||||
- Better ways to structure
|
||||
- New categories needed
|
||||
|
||||
Please submit an issue with the "documentation" template to suggest improvements!
|
||||
|
||||
## Related Files
|
||||
|
||||
- **Workflow Guide**: `.github/prompts/0-kickstart.md`
|
||||
- **Contributing**: `README.md` → Contributing section
|
||||
- **Architecture**: `docs/architecture/`
|
||||
- **DBAL Guide**: `dbal/docs/AGENTS.md`
|
||||
- **UI Standards**: `UI_STANDARDS.md`
|
||||
- **Copilot Instructions**: `.github/copilot-instructions.md`
|
||||
# Issue and Pull Request Templates
|
||||
|
||||
This document describes the issue and PR templates available for MetaBuilder and how to use them effectively.
|
||||
|
||||
## Overview
|
||||
|
||||
MetaBuilder uses structured templates to ensure consistent, high-quality issues and pull requests. These templates are specifically designed for MetaBuilder's data-driven, multi-tenant architecture.
|
||||
|
||||
## Issue Templates
|
||||
|
||||
### Available Templates
|
||||
|
||||
#### 🐛 Bug Report (`bug_report.yml`)
|
||||
Use this template to report bugs or unexpected behavior.
|
||||
|
||||
**Key Features:**
|
||||
- Environment details capture (OS, Node version, browser, database)
|
||||
- Severity levels (Critical, High, Medium, Low)
|
||||
- Component categorization
|
||||
- Reproducible steps
|
||||
- Pre-submission checklist
|
||||
|
||||
**Best For:**
|
||||
- Application crashes or errors
|
||||
- Features not working as expected
|
||||
- Performance issues
|
||||
- UI/UX bugs
|
||||
|
||||
#### ✨ Feature Request (`feature_request.yml`)
|
||||
Request new features or enhancements aligned with MetaBuilder's architecture.
|
||||
|
||||
**Key Features:**
|
||||
- Problem statement and solution proposal
|
||||
- Target user permission levels (Level 1-6)
|
||||
- Priority assessment
|
||||
- Use case descriptions
|
||||
- Technical considerations
|
||||
- Contribution willingness
|
||||
|
||||
**Best For:**
|
||||
- New feature ideas
|
||||
- Improvements to existing features
|
||||
- API enhancements
|
||||
- User experience improvements
|
||||
|
||||
#### 📚 Documentation (`documentation.yml`)
|
||||
Report documentation issues or request improvements.
|
||||
|
||||
**Key Features:**
|
||||
- Documentation type categorization
|
||||
- Location/path specification
|
||||
- Suggested improvements
|
||||
- Documentation area targeting
|
||||
|
||||
**Best For:**
|
||||
- Missing documentation
|
||||
- Outdated information
|
||||
- Unclear explanations
|
||||
- Broken links or typos
|
||||
- Missing code examples
|
||||
|
||||
#### 📦 Package Request (`package_request.yml`)
|
||||
Request new packages for MetaBuilder's package system.
|
||||
|
||||
**Key Features:**
|
||||
- Package naming (snake_case convention)
|
||||
- Package type selection
|
||||
- Minimum permission level
|
||||
- Component and Lua script planning
|
||||
- Database schema requirements
|
||||
- Multi-tenant consideration
|
||||
|
||||
**Best For:**
|
||||
- New package ideas
|
||||
- Package integrations
|
||||
- Package improvements
|
||||
- Community packages
|
||||
|
||||
**Special Considerations:**
|
||||
- Package names must use snake_case
|
||||
- Must specify multi-tenant requirements
|
||||
- Should include Lua script needs (MetaBuilder is 95% JSON/Lua)
|
||||
- Must declare dependencies
|
||||
|
||||
#### 🔧 DBAL Issue (`dbal_issue.yml`)
|
||||
Report issues with the Database Abstraction Layer.
|
||||
|
||||
**Key Features:**
|
||||
- Implementation selection (TypeScript/C++)
|
||||
- Operation type categorization
|
||||
- Conformance test status
|
||||
- Implementation parity checks
|
||||
- Severity levels
|
||||
|
||||
**Best For:**
|
||||
- DBAL TypeScript SDK issues (`dbal/ts/`)
|
||||
- DBAL C++ daemon issues (`dbal/production/`)
|
||||
- YAML contract problems (`api/schema/`)
|
||||
- Conformance test failures
|
||||
- Implementation inconsistencies
|
||||
|
||||
**Special Considerations:**
|
||||
- Check YAML schema definitions first
|
||||
- Run conformance tests if applicable
|
||||
- Verify tenant isolation
|
||||
- Note if both implementations behave differently
|
||||
|
||||
### Template Configuration (`config.yml`)
|
||||
|
||||
The config file provides:
|
||||
- Documentation links
|
||||
- Community discussion links
|
||||
- Private security reporting
|
||||
- Disables blank issues to ensure structure
|
||||
|
||||
## Pull Request Template
|
||||
|
||||
### Structure
|
||||
|
||||
The PR template (`PULL_REQUEST_TEMPLATE.md`) includes comprehensive sections:
|
||||
|
||||
#### 1. Basic Information
|
||||
- Description of changes
|
||||
- Related issue linking
|
||||
- Type of change
|
||||
- Component/area affected
|
||||
|
||||
#### 2. Changes Made
|
||||
- Detailed list of code changes
|
||||
- Database/schema changes
|
||||
- Configuration changes
|
||||
|
||||
#### 3. Testing
|
||||
- Test coverage (unit, integration, E2E)
|
||||
- Manual testing verification
|
||||
- Permission level testing
|
||||
- Multi-tenant scenario testing
|
||||
|
||||
#### 4. Architecture & Design Decisions
|
||||
|
||||
**Data-Driven Approach:**
|
||||
- Verify JSON/Lua architecture alignment
|
||||
- Use of declarative components
|
||||
- DBAL usage for database operations
|
||||
|
||||
**Multi-Tenancy:**
|
||||
- TenantId filtering verification
|
||||
- Tenant isolation checks
|
||||
|
||||
**Permission System:**
|
||||
- Permission checks at correct levels
|
||||
- AuthGate/canAccessLevel usage
|
||||
|
||||
**Package System:**
|
||||
- Metadata structure compliance
|
||||
- Naming conventions (snake_case, semver)
|
||||
- Dependency declarations
|
||||
|
||||
**Security:**
|
||||
- Input validation
|
||||
- XSS/SQL injection checks
|
||||
- Password hashing (SHA-512)
|
||||
- Lua sandbox restrictions
|
||||
- No secrets in code
|
||||
|
||||
#### 5. Breaking Changes
|
||||
- Migration steps
|
||||
- Impact assessment
|
||||
- Upgrade guide
|
||||
|
||||
#### 6. Documentation
|
||||
- README updates
|
||||
- API documentation
|
||||
- Architecture docs
|
||||
- Migration guides
|
||||
|
||||
#### 7. Pre-Submission Checklist
|
||||
|
||||
**Code Quality:**
|
||||
- Follows conventions (one lambda per file)
|
||||
- Uses MUI (not Radix/Tailwind)
|
||||
- ESLint passes
|
||||
- TypeScript compiles
|
||||
|
||||
**Testing:**
|
||||
- All tests pass
|
||||
- Test coverage adequate
|
||||
- E2E tests pass (if applicable)
|
||||
- Cross-browser testing (if UI)
|
||||
|
||||
**Database & Schema:**
|
||||
- Prisma schema validated
|
||||
- Migrations tested
|
||||
- DBAL conformance tests pass
|
||||
|
||||
**Security:**
|
||||
- Vulnerabilities checked
|
||||
- Input validation implemented
|
||||
- No sensitive data committed
|
||||
|
||||
**MetaBuilder-Specific:**
|
||||
- Data-driven architecture alignment
|
||||
- Multi-tenant safety verified
|
||||
- Permission checks correct
|
||||
- DBAL used (not raw Prisma)
|
||||
- Generic components where possible
|
||||
|
||||
#### 8. Additional Sections
|
||||
- Deployment considerations
|
||||
- Reviewer notes
|
||||
- Focus areas for review
|
||||
|
||||
## Using the Templates
|
||||
|
||||
### Creating an Issue
|
||||
|
||||
1. Go to the [Issues page](https://github.com/johndoe6345789/metabuilder/issues)
|
||||
2. Click "New issue"
|
||||
3. Select the appropriate template
|
||||
4. Fill in all required fields (marked with red asterisk)
|
||||
5. Complete the pre-submission checklist
|
||||
6. Submit the issue
|
||||
|
||||
### Creating a Pull Request
|
||||
|
||||
1. Push your branch to GitHub
|
||||
2. Navigate to the repository
|
||||
3. Click "Pull requests" → "New pull request"
|
||||
4. Select your branch
|
||||
5. The PR template will auto-populate
|
||||
6. Fill in all sections thoroughly
|
||||
7. Mark checkboxes in the pre-submission checklist
|
||||
8. Submit the PR
|
||||
|
||||
### Template Tips
|
||||
|
||||
**For Issues:**
|
||||
- Be specific and detailed
|
||||
- Include reproduction steps for bugs
|
||||
- Provide environment details
|
||||
- Search for duplicates first
|
||||
- Check documentation before submitting
|
||||
|
||||
**For PRs:**
|
||||
- Link related issues
|
||||
- Include screenshots for UI changes
|
||||
- Document breaking changes clearly
|
||||
- Run all tests before submitting
|
||||
- Complete the entire checklist
|
||||
- Focus on minimal, surgical changes
|
||||
|
||||
## MetaBuilder-Specific Guidelines
|
||||
|
||||
### Data-Driven Architecture
|
||||
MetaBuilder is 95% JSON/Lua, not TypeScript. When contributing:
|
||||
- Prefer JSON/Lua configuration over hardcoded TS
|
||||
- Use `RenderComponent` for declarative UI
|
||||
- Add Lua scripts to `packages/*/seed/scripts/`
|
||||
- Keep TypeScript as adapters/wrappers
|
||||
|
||||
### Multi-Tenancy
|
||||
All contributions must respect tenant isolation:
|
||||
- Include `tenantId` in all queries
|
||||
- Use `Database` class methods, not raw Prisma
|
||||
- Test with multiple tenants
|
||||
- Document tenant-specific behavior
|
||||
|
||||
### Permission System (Levels 1-6)
|
||||
- Level 1: Public (no auth)
|
||||
- Level 2: User (basic auth)
|
||||
- Level 3: Moderator (content moderation)
|
||||
- Level 4: Admin (user management)
|
||||
- Level 5: God (system config, packages)
|
||||
- Level 6: Supergod (full system control)
|
||||
|
||||
When adding features, specify the minimum required level and use `canAccessLevel()` checks.
|
||||
|
||||
### Package System
|
||||
Packages follow strict conventions:
|
||||
- Name: `snake_case` (e.g., `blog_engine`)
|
||||
- Version: Semver (e.g., `1.2.3`)
|
||||
- Structure: `packages/{name}/seed/` with `metadata.json`, `components.json`
|
||||
- Lua scripts in `packages/{name}/seed/scripts/`
|
||||
- Optional React components in `packages/{name}/src/`
|
||||
|
||||
### DBAL (Database Abstraction Layer)
|
||||
- TypeScript implementation: `dbal/ts/` (development)
|
||||
- C++ implementation: `dbal/production/` (production)
|
||||
- YAML contracts: `api/schema/` (source of truth)
|
||||
- Always update YAML first
|
||||
- Run conformance tests: `python tools/conformance/run_all.py`
|
||||
- Ensure both implementations behave identically
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Issue Reporting
|
||||
1. **Search first**: Check if the issue already exists
|
||||
2. **Be specific**: Provide exact steps and details
|
||||
3. **Be respectful**: Follow the code of conduct
|
||||
4. **Be patient**: Maintainers will respond when available
|
||||
5. **Follow up**: Provide additional info if requested
|
||||
|
||||
### Pull Requests
|
||||
1. **Small changes**: Keep PRs focused and minimal
|
||||
2. **Test thoroughly**: Run all tests and linters
|
||||
3. **Document well**: Update docs with changes
|
||||
4. **Follow conventions**: Match existing code style
|
||||
5. **Respond quickly**: Address review feedback promptly
|
||||
|
||||
### Security
|
||||
- **Never commit secrets**: No API keys, passwords, tokens
|
||||
- **Report privately**: Use GitHub Security Advisories for vulnerabilities
|
||||
- **Hash passwords**: Always use SHA-512 via `password-utils.ts`
|
||||
- **Validate input**: Never trust user input
|
||||
- **Sandbox Lua**: Maintain Lua script restrictions
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you have questions about the templates or contribution process:
|
||||
|
||||
1. **Documentation**: Check [docs/](../docs/) for guides
|
||||
2. **Discussions**: Ask in [GitHub Discussions](https://github.com/johndoe6345789/metabuilder/discussions)
|
||||
3. **Examples**: Look at existing issues and PRs
|
||||
4. **Workflow Guide**: See `.github/prompts/0-kickstart.md`
|
||||
|
||||
## Template Maintenance
|
||||
|
||||
These templates are living documents. If you find:
|
||||
- Missing fields or options
|
||||
- Unclear instructions
|
||||
- Better ways to structure
|
||||
- New categories needed
|
||||
|
||||
Please submit an issue with the "documentation" template to suggest improvements!
|
||||
|
||||
## Related Files
|
||||
|
||||
- **Workflow Guide**: `.github/prompts/0-kickstart.md`
|
||||
- **Contributing**: `README.md` → Contributing section
|
||||
- **Architecture**: `docs/architecture/`
|
||||
- **DBAL Guide**: `dbal/docs/AGENTS.md`
|
||||
- **UI Standards**: `UI_STANDARDS.md`
|
||||
- **Copilot Instructions**: `.github/copilot-instructions.md`
|
||||
|
||||
494
.github/copilot-instructions.md
vendored
494
.github/copilot-instructions.md
vendored
@@ -1,247 +1,247 @@
|
||||
# GitHub Copilot Instructions for MetaBuilder
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
MetaBuilder is a **data-driven, multi-tenant platform** with 95% functionality in JSON/Lua, not TypeScript. The system combines:
|
||||
|
||||
- **6-Level Permission System**: Public → User → Moderator → Admin → God → Supergod access hierarchies
|
||||
- **DBAL (Database Abstraction Layer)**: TypeScript SDK + C++ daemon, language-agnostic via YAML contracts
|
||||
- **Declarative Components**: Render complex UIs from JSON configuration using `RenderComponent`
|
||||
- **Package System**: Self-contained modules in `/packages/{name}/seed/` with metadata, components, scripts
|
||||
- **Multi-Source Package Repos**: Support for local and remote package registries via `PackageSourceManager`
|
||||
- **Multi-Tenancy**: All data queries filter by `tenantId`; each tenant has isolated configurations
|
||||
|
||||
## 0-kickstart Operating Rules
|
||||
|
||||
Follow `.github/prompts/0-kickstart.md` as the current workflow source of truth. Key rules:
|
||||
- Work through `.github/prompts/` as needed; start with `0-kickstart.md`.
|
||||
- Commit as you go with descriptive messages; default to trunking on `main`.
|
||||
- Use `act` to diagnose GitHub workflow issues locally.
|
||||
- Keep unit tests parameterized; create new test files where possible; use 1:1 source-to-test naming.
|
||||
- Leave TODO comments for missing functionality.
|
||||
- Check `docs/todo/` before starting.
|
||||
- One lambda per file; classes only serve as containers for related lambdas (see `.github/prompts/LAMBDA_PROMPT.md`).
|
||||
- Route data access through DBAL; treat it as the trusted layer.
|
||||
- Design for flexibility, modularity, and containerization.
|
||||
- See `docs/RADIX_TO_MUI_MIGRATION.md` for UI migration guidance.
|
||||
|
||||
## Critical Patterns
|
||||
|
||||
### 1. API-First DBAL Development
|
||||
When adding features to DBAL:
|
||||
1. **Define in YAML first**: `api/schema/entities/*.yaml` and `api/schema/operations/*.yaml`
|
||||
2. **Generate types**: `python tools/codegen/gen_types.py` (creates TS and C++ types)
|
||||
3. **Implement adapters**: TypeScript (`ts/src/adapters/`) for speed, C++ (`cpp/src/adapters/`) for security
|
||||
4. **Add conformance tests**: `common/contracts/*_tests.yaml` (runs on both implementations to guarantee parity)
|
||||
5. Never add fields/operations directly in code without updating YAML source of truth
|
||||
|
||||
**Why**: C++ daemon isolates credentials (users never see DB URLs), enforces row-level security, and protects against malicious queries.
|
||||
|
||||
### 2. Generic Component Rendering
|
||||
Instead of hardcoded components, use declarative config:
|
||||
```tsx
|
||||
// ❌ Wrong: Hardcoded
|
||||
<UserForm user={user} onSave={handleSave} />
|
||||
|
||||
// ✅ Right: Declarative
|
||||
<RenderComponent component={{
|
||||
type: 'form',
|
||||
props: { schema: formSchema },
|
||||
children: [/* field components */]
|
||||
}} />
|
||||
```
|
||||
See: `RenderComponent.tsx`, `declarative-component-renderer.ts`
|
||||
|
||||
### 3. Package Seed Data Structure
|
||||
Each package auto-loads on init:
|
||||
```
|
||||
packages/{name}/
|
||||
├── seed/
|
||||
│ ├── metadata.json # Package info, exports, dependencies, minLevel
|
||||
│ ├── components.json # Component definitions
|
||||
│ ├── scripts/ # Lua scripts organized by function
|
||||
│ └── index.ts # Exports packageSeed object
|
||||
├── src/ # Optional React components
|
||||
└── static_content/ # Assets (images, etc.)
|
||||
```
|
||||
Loaded by `initializePackageSystem()` → `buildPackageRegistry()` → `exportAllPackagesForSeed()`
|
||||
|
||||
### 3a. Multi-Source Package Repositories
|
||||
Packages can come from multiple sources:
|
||||
```typescript
|
||||
import { createPackageSourceManager, LocalPackageSource, RemotePackageSource } from '@/lib/packages/package-glue'
|
||||
|
||||
const manager = createPackageSourceManager({
|
||||
enableRemote: true,
|
||||
remoteUrl: 'https://registry.metabuilder.dev/api/v1',
|
||||
conflictResolution: 'priority' // or 'latest-version', 'local-first', 'remote-first'
|
||||
})
|
||||
|
||||
const packages = await manager.fetchMergedIndex()
|
||||
const pkg = await manager.loadPackage('dashboard')
|
||||
```
|
||||
See: `docs/packages/package-sources.md`, `package-glue/sources/`
|
||||
|
||||
### 4. Database Helpers Pattern
|
||||
Always use `Database` class methods, never raw Prisma:
|
||||
```typescript
|
||||
// ✅ Right
|
||||
const users = await Database.getUsers()
|
||||
await Database.setSchemas(schemas)
|
||||
|
||||
// ❌ Wrong
|
||||
const users = await prisma.user.findMany()
|
||||
```
|
||||
See: `src/lib/database.ts` (1200+ LOC utility wrapper)
|
||||
|
||||
### 5. Lua Sandbox Execution
|
||||
Lua scripts run in isolated sandbox without access to `os`, `io`, `require`:
|
||||
```typescript
|
||||
// Sandbox context provided in script
|
||||
function validateEmail(email)
|
||||
-- No file I/O, no system access, no external requires
|
||||
return string.match(email, "^[^@]+@[^@]+$") ~= nil
|
||||
end
|
||||
```
|
||||
Always test scripts with `DeclarativeComponentRenderer.executeLuaScript()`
|
||||
|
||||
## Code Conventions
|
||||
|
||||
### UI Components & Styling
|
||||
|
||||
**⚠️ CRITICAL: This project does NOT use Radix UI or Tailwind CSS**
|
||||
|
||||
- ❌ **NEVER import from `@radix-ui/*`** - These dependencies have been removed
|
||||
- ❌ **NEVER use Tailwind utility classes** in `className` props
|
||||
- ✅ **ALWAYS use Material-UI** (`@mui/material`) for UI components
|
||||
- ✅ **Use MUI's `sx` prop** for inline styles with theme access
|
||||
- ✅ **Create `.module.scss` files** for component-specific custom styles
|
||||
- ✅ **Use `@mui/icons-material`** for icons, not lucide-react or heroicons
|
||||
|
||||
```tsx
|
||||
// ❌ Wrong: Using Radix UI or Tailwind
|
||||
import { Dialog } from '@radix-ui/react-dialog'
|
||||
<button className="bg-blue-500 text-white px-4 py-2">Click</button>
|
||||
|
||||
// ✅ Right: Using Material-UI
|
||||
import { Dialog, Button } from '@mui/material'
|
||||
<Button variant="contained" color="primary">Click</Button>
|
||||
<Box sx={{ display: 'flex', gap: 2, p: 3 }}>Content</Box>
|
||||
```
|
||||
|
||||
**Component Mapping:**
|
||||
- Radix Dialog → MUI Dialog
|
||||
- Radix Select → MUI Select
|
||||
- Radix Checkbox → MUI Checkbox
|
||||
- Radix Switch → MUI Switch
|
||||
- Tailwind classes → MUI `sx` prop or SCSS modules
|
||||
|
||||
**See:** `UI_STANDARDS.md` and `docs/UI_MIGRATION.md` for complete reference
|
||||
|
||||
### TypeScript/React
|
||||
- One lambda per file; classes are containers for related lambdas.
|
||||
- Keep files small and focused; split by responsibility when they grow.
|
||||
- Use `@/` absolute paths
|
||||
- Functional components with hooks; avoid class components
|
||||
- Test files next to source with matching names: `utils.ts` + `utils.test.ts`, using parameterized `it.each()`
|
||||
|
||||
### Tests
|
||||
All functions need coverage with parameterized tests:
|
||||
```typescript
|
||||
// From schema-utils.test.ts: 63 tests for 14 functions
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
```
|
||||
Run `npm run test:coverage:report` to auto-generate coverage markdown.
|
||||
|
||||
### Database
|
||||
- Schema in `prisma/schema.prisma`, always run `npm run db:generate` after changes
|
||||
- Hash passwords with SHA-512 (see `password-utils.ts`)
|
||||
- Queries must include `where('tenantId', currentTenant.id)` for multi-tenancy
|
||||
|
||||
### Styling
|
||||
Material-UI with SASS; theme in `src/theme/mui-theme.ts` with light/dark mode support. Font families: IBM Plex Sans (body), Space Grotesk (headings), JetBrains Mono (code). Use MUI's `sx` prop for inline styles or create `.module.scss` files for custom component styles.
|
||||
|
||||
## Development Checklist
|
||||
|
||||
**Before implementing**: Check `docs/` and `docs/todo/`, and review `.github/prompts/0-kickstart.md` for current workflow rules.
|
||||
|
||||
**During implementation**:
|
||||
1. Define database schema changes first (Prisma)
|
||||
2. Add seed data to `src/seed-data/` or package `/seed/`
|
||||
3. Use generic renderers (`RenderComponent`) not hardcoded JSX
|
||||
4. Add Lua scripts in `src/lib/lua-snippets.ts` or package `/seed/scripts/`
|
||||
5. Keep one lambda per file and split as needed
|
||||
6. Add parameterized tests in `.test.ts` files with matching names
|
||||
|
||||
**Before commit**:
|
||||
- `npm run lint:fix` (fixes ESLint issues)
|
||||
- `npm test -- --run` (all tests pass)
|
||||
- `npm run test:coverage:report` (verify new functions have tests)
|
||||
- `npm run test:e2e` (critical workflows still work)
|
||||
- Use `npm run act:diagnose` or `npm run act` when investigating CI/workflow failures
|
||||
- Commit with a descriptive message on `main` unless a PR workflow is explicitly required
|
||||
|
||||
## Multi-Tenant Safety
|
||||
|
||||
Every query must filter by tenant:
|
||||
```typescript
|
||||
// ❌ Never
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Always
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
Permission checks cascade from lowest level:
|
||||
```typescript
|
||||
if (user.level >= 3) { // Admin and above
|
||||
showAdminPanel()
|
||||
}
|
||||
```
|
||||
|
||||
## DBAL-Specific Guidance
|
||||
|
||||
**TypeScript DBAL**: Fast iteration, development use. Located in `dbal/ts/src/`.
|
||||
**C++ DBAL Daemon**: Production security, credential protection. Located in `dbal/production/src/`.
|
||||
**Conformance Tests**: Guarantee both implementations behave identically. Update `common/contracts/` when changing YAML schemas.
|
||||
|
||||
If fixing a DBAL bug:
|
||||
1. Verify the bug exists in YAML schema definition
|
||||
2. Reproduce in TypeScript implementation first (faster feedback loop)
|
||||
3. Apply fix to both TS and C++ adapters
|
||||
4. Add/update conformance test in `common/contracts/`
|
||||
5. Verify both implementations pass test: `python tools/conformance/run_all.py`
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
❌ **Hardcoding values in TSX** → Move to database or YAML config
|
||||
❌ **Forgetting tenantId filter** → Breaks multi-tenancy
|
||||
❌ **Adding fields without Prisma generate** → Type errors in DB helper
|
||||
❌ **Plain JS loops over Fengari tables** → Use Lua, not TS, for Lua data
|
||||
❌ **Multiple lambdas per file** → Split into single-lambda files and wrap with a class only when needed
|
||||
❌ **New function without test** → `npm run test:check-functions` will fail
|
||||
❌ **Missing TODO for unfinished behavior** → Leave a TODO comment where functionality is pending
|
||||
|
||||
## Key Files
|
||||
|
||||
- **Architecture**: `docs/architecture/5-level-system.md` (permissions), `docs/architecture/packages.md` (packages)
|
||||
- **Components**: `src/components/RenderComponent.tsx` (generic renderer), `src/lib/declarative-component-renderer.ts`
|
||||
- **Database**: `src/lib/database.ts` (all DB operations), `prisma/schema.prisma` (schema)
|
||||
- **Packages**: `src/lib/package-loader.ts` (initialization), `packages/*/seed/` (definitions)
|
||||
- **Tests**: `src/lib/schema-utils.test.ts` (parameterized pattern), `FUNCTION_TEST_COVERAGE.md` (auto-generated report)
|
||||
- **DBAL**: `dbal/docs/AGENTS.md` (detailed DBAL agent guide), `api/schema/` (YAML contracts)
|
||||
|
||||
## Questions to Ask
|
||||
|
||||
1. Is this hardcoded value better in database?
|
||||
2. Could a generic component render this instead of custom TSX?
|
||||
3. Does this query filter by tenantId?
|
||||
4. Could Lua handle this without code changes?
|
||||
5. Is this one lambda per file (and test file name matches)?
|
||||
6. Does this function have a parameterized test?
|
||||
7. Is this DBAL change reflected in YAML schema first?
|
||||
# GitHub Copilot Instructions for MetaBuilder
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
MetaBuilder is a **data-driven, multi-tenant platform** with 95% functionality in JSON/Lua, not TypeScript. The system combines:
|
||||
|
||||
- **6-Level Permission System**: Public → User → Moderator → Admin → God → Supergod access hierarchies
|
||||
- **DBAL (Database Abstraction Layer)**: TypeScript SDK + C++ daemon, language-agnostic via YAML contracts
|
||||
- **Declarative Components**: Render complex UIs from JSON configuration using `RenderComponent`
|
||||
- **Package System**: Self-contained modules in `/packages/{name}/seed/` with metadata, components, scripts
|
||||
- **Multi-Source Package Repos**: Support for local and remote package registries via `PackageSourceManager`
|
||||
- **Multi-Tenancy**: All data queries filter by `tenantId`; each tenant has isolated configurations
|
||||
|
||||
## 0-kickstart Operating Rules
|
||||
|
||||
Follow `.github/prompts/0-kickstart.md` as the current workflow source of truth. Key rules:
|
||||
- Work through `.github/prompts/` as needed; start with `0-kickstart.md`.
|
||||
- Commit as you go with descriptive messages; default to trunking on `main`.
|
||||
- Use `act` to diagnose GitHub workflow issues locally.
|
||||
- Keep unit tests parameterized; create new test files where possible; use 1:1 source-to-test naming.
|
||||
- Leave TODO comments for missing functionality.
|
||||
- Check `docs/todo/` before starting.
|
||||
- One lambda per file; classes only serve as containers for related lambdas (see `.github/prompts/LAMBDA_PROMPT.md`).
|
||||
- Route data access through DBAL; treat it as the trusted layer.
|
||||
- Design for flexibility, modularity, and containerization.
|
||||
- See `docs/RADIX_TO_MUI_MIGRATION.md` for UI migration guidance.
|
||||
|
||||
## Critical Patterns
|
||||
|
||||
### 1. API-First DBAL Development
|
||||
When adding features to DBAL:
|
||||
1. **Define in YAML first**: `api/schema/entities/*.yaml` and `api/schema/operations/*.yaml`
|
||||
2. **Generate types**: `python tools/codegen/gen_types.py` (creates TS and C++ types)
|
||||
3. **Implement adapters**: TypeScript (`ts/src/adapters/`) for speed, C++ (`cpp/src/adapters/`) for security
|
||||
4. **Add conformance tests**: `common/contracts/*_tests.yaml` (runs on both implementations to guarantee parity)
|
||||
5. Never add fields/operations directly in code without updating YAML source of truth
|
||||
|
||||
**Why**: C++ daemon isolates credentials (users never see DB URLs), enforces row-level security, and protects against malicious queries.
|
||||
|
||||
### 2. Generic Component Rendering
|
||||
Instead of hardcoded components, use declarative config:
|
||||
```tsx
|
||||
// ❌ Wrong: Hardcoded
|
||||
<UserForm user={user} onSave={handleSave} />
|
||||
|
||||
// ✅ Right: Declarative
|
||||
<RenderComponent component={{
|
||||
type: 'form',
|
||||
props: { schema: formSchema },
|
||||
children: [/* field components */]
|
||||
}} />
|
||||
```
|
||||
See: `RenderComponent.tsx`, `declarative-component-renderer.ts`
|
||||
|
||||
### 3. Package Seed Data Structure
|
||||
Each package auto-loads on init:
|
||||
```
|
||||
packages/{name}/
|
||||
├── seed/
|
||||
│ ├── metadata.json # Package info, exports, dependencies, minLevel
|
||||
│ ├── components.json # Component definitions
|
||||
│ ├── scripts/ # Lua scripts organized by function
|
||||
│ └── index.ts # Exports packageSeed object
|
||||
├── src/ # Optional React components
|
||||
└── static_content/ # Assets (images, etc.)
|
||||
```
|
||||
Loaded by `initializePackageSystem()` → `buildPackageRegistry()` → `exportAllPackagesForSeed()`
|
||||
|
||||
### 3a. Multi-Source Package Repositories
|
||||
Packages can come from multiple sources:
|
||||
```typescript
|
||||
import { createPackageSourceManager, LocalPackageSource, RemotePackageSource } from '@/lib/packages/package-glue'
|
||||
|
||||
const manager = createPackageSourceManager({
|
||||
enableRemote: true,
|
||||
remoteUrl: 'https://registry.metabuilder.dev/api/v1',
|
||||
conflictResolution: 'priority' // or 'latest-version', 'local-first', 'remote-first'
|
||||
})
|
||||
|
||||
const packages = await manager.fetchMergedIndex()
|
||||
const pkg = await manager.loadPackage('dashboard')
|
||||
```
|
||||
See: `docs/packages/package-sources.md`, `package-glue/sources/`
|
||||
|
||||
### 4. Database Helpers Pattern
|
||||
Always use `Database` class methods, never raw Prisma:
|
||||
```typescript
|
||||
// ✅ Right
|
||||
const users = await Database.getUsers()
|
||||
await Database.setSchemas(schemas)
|
||||
|
||||
// ❌ Wrong
|
||||
const users = await prisma.user.findMany()
|
||||
```
|
||||
See: `src/lib/database.ts` (1200+ LOC utility wrapper)
|
||||
|
||||
### 5. Lua Sandbox Execution
|
||||
Lua scripts run in isolated sandbox without access to `os`, `io`, `require`:
|
||||
```typescript
|
||||
// Sandbox context provided in script
|
||||
function validateEmail(email)
|
||||
-- No file I/O, no system access, no external requires
|
||||
return string.match(email, "^[^@]+@[^@]+$") ~= nil
|
||||
end
|
||||
```
|
||||
Always test scripts with `DeclarativeComponentRenderer.executeLuaScript()`
|
||||
|
||||
## Code Conventions
|
||||
|
||||
### UI Components & Styling
|
||||
|
||||
**⚠️ CRITICAL: This project does NOT use Radix UI or Tailwind CSS**
|
||||
|
||||
- ❌ **NEVER import from `@radix-ui/*`** - These dependencies have been removed
|
||||
- ❌ **NEVER use Tailwind utility classes** in `className` props
|
||||
- ✅ **ALWAYS use Material-UI** (`@mui/material`) for UI components
|
||||
- ✅ **Use MUI's `sx` prop** for inline styles with theme access
|
||||
- ✅ **Create `.module.scss` files** for component-specific custom styles
|
||||
- ✅ **Use `@mui/icons-material`** for icons, not lucide-react or heroicons
|
||||
|
||||
```tsx
|
||||
// ❌ Wrong: Using Radix UI or Tailwind
|
||||
import { Dialog } from '@radix-ui/react-dialog'
|
||||
<button className="bg-blue-500 text-white px-4 py-2">Click</button>
|
||||
|
||||
// ✅ Right: Using Material-UI
|
||||
import { Dialog, Button } from '@mui/material'
|
||||
<Button variant="contained" color="primary">Click</Button>
|
||||
<Box sx={{ display: 'flex', gap: 2, p: 3 }}>Content</Box>
|
||||
```
|
||||
|
||||
**Component Mapping:**
|
||||
- Radix Dialog → MUI Dialog
|
||||
- Radix Select → MUI Select
|
||||
- Radix Checkbox → MUI Checkbox
|
||||
- Radix Switch → MUI Switch
|
||||
- Tailwind classes → MUI `sx` prop or SCSS modules
|
||||
|
||||
**See:** `UI_STANDARDS.md` and `docs/UI_MIGRATION.md` for complete reference
|
||||
|
||||
### TypeScript/React
|
||||
- One lambda per file; classes are containers for related lambdas.
|
||||
- Keep files small and focused; split by responsibility when they grow.
|
||||
- Use `@/` absolute paths
|
||||
- Functional components with hooks; avoid class components
|
||||
- Test files next to source with matching names: `utils.ts` + `utils.test.ts`, using parameterized `it.each()`
|
||||
|
||||
### Tests
|
||||
All functions need coverage with parameterized tests:
|
||||
```typescript
|
||||
// From schema-utils.test.ts: 63 tests for 14 functions
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
```
|
||||
Run `npm run test:coverage:report` to auto-generate coverage markdown.
|
||||
|
||||
### Database
|
||||
- Schema in `prisma/schema.prisma`, always run `npm run db:generate` after changes
|
||||
- Hash passwords with SHA-512 (see `password-utils.ts`)
|
||||
- Queries must include `where('tenantId', currentTenant.id)` for multi-tenancy
|
||||
|
||||
### Styling
|
||||
Material-UI with SASS; theme in `src/theme/mui-theme.ts` with light/dark mode support. Font families: IBM Plex Sans (body), Space Grotesk (headings), JetBrains Mono (code). Use MUI's `sx` prop for inline styles or create `.module.scss` files for custom component styles.
|
||||
|
||||
## Development Checklist
|
||||
|
||||
**Before implementing**: Check `docs/` and `docs/todo/`, and review `.github/prompts/0-kickstart.md` for current workflow rules.
|
||||
|
||||
**During implementation**:
|
||||
1. Define database schema changes first (Prisma)
|
||||
2. Add seed data to `src/seed-data/` or package `/seed/`
|
||||
3. Use generic renderers (`RenderComponent`) not hardcoded JSX
|
||||
4. Add Lua scripts in `src/lib/lua-snippets.ts` or package `/seed/scripts/`
|
||||
5. Keep one lambda per file and split as needed
|
||||
6. Add parameterized tests in `.test.ts` files with matching names
|
||||
|
||||
**Before commit**:
|
||||
- `npm run lint:fix` (fixes ESLint issues)
|
||||
- `npm test -- --run` (all tests pass)
|
||||
- `npm run test:coverage:report` (verify new functions have tests)
|
||||
- `npm run test:e2e` (critical workflows still work)
|
||||
- Use `npm run act:diagnose` or `npm run act` when investigating CI/workflow failures
|
||||
- Commit with a descriptive message on `main` unless a PR workflow is explicitly required
|
||||
|
||||
## Multi-Tenant Safety
|
||||
|
||||
Every query must filter by tenant:
|
||||
```typescript
|
||||
// ❌ Never
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Always
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
Permission checks cascade from lowest level:
|
||||
```typescript
|
||||
if (user.level >= 3) { // Admin and above
|
||||
showAdminPanel()
|
||||
}
|
||||
```
|
||||
|
||||
## DBAL-Specific Guidance
|
||||
|
||||
**TypeScript DBAL**: Fast iteration, development use. Located in `dbal/ts/src/`.
|
||||
**C++ DBAL Daemon**: Production security, credential protection. Located in `dbal/production/src/`.
|
||||
**Conformance Tests**: Guarantee both implementations behave identically. Update `common/contracts/` when changing YAML schemas.
|
||||
|
||||
If fixing a DBAL bug:
|
||||
1. Verify the bug exists in YAML schema definition
|
||||
2. Reproduce in TypeScript implementation first (faster feedback loop)
|
||||
3. Apply fix to both TS and C++ adapters
|
||||
4. Add/update conformance test in `common/contracts/`
|
||||
5. Verify both implementations pass test: `python tools/conformance/run_all.py`
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
❌ **Hardcoding values in TSX** → Move to database or YAML config
|
||||
❌ **Forgetting tenantId filter** → Breaks multi-tenancy
|
||||
❌ **Adding fields without Prisma generate** → Type errors in DB helper
|
||||
❌ **Plain JS loops over Fengari tables** → Use Lua, not TS, for Lua data
|
||||
❌ **Multiple lambdas per file** → Split into single-lambda files and wrap with a class only when needed
|
||||
❌ **New function without test** → `npm run test:check-functions` will fail
|
||||
❌ **Missing TODO for unfinished behavior** → Leave a TODO comment where functionality is pending
|
||||
|
||||
## Key Files
|
||||
|
||||
- **Architecture**: `docs/architecture/5-level-system.md` (permissions), `docs/architecture/packages.md` (packages)
|
||||
- **Components**: `src/components/RenderComponent.tsx` (generic renderer), `src/lib/declarative-component-renderer.ts`
|
||||
- **Database**: `src/lib/database.ts` (all DB operations), `prisma/schema.prisma` (schema)
|
||||
- **Packages**: `src/lib/package-loader.ts` (initialization), `packages/*/seed/` (definitions)
|
||||
- **Tests**: `src/lib/schema-utils.test.ts` (parameterized pattern), `FUNCTION_TEST_COVERAGE.md` (auto-generated report)
|
||||
- **DBAL**: `dbal/docs/AGENTS.md` (detailed DBAL agent guide), `api/schema/` (YAML contracts)
|
||||
|
||||
## Questions to Ask
|
||||
|
||||
1. Is this hardcoded value better in database?
|
||||
2. Could a generic component render this instead of custom TSX?
|
||||
3. Does this query filter by tenantId?
|
||||
4. Could Lua handle this without code changes?
|
||||
5. Is this one lambda per file (and test file name matches)?
|
||||
6. Does this function have a parameterized test?
|
||||
7. Is this DBAL change reflected in YAML schema first?
|
||||
|
||||
22
.github/dependabot.yml
vendored
22
.github/dependabot.yml
vendored
@@ -1,11 +1,11 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# Run GitHub Actions Locally
|
||||
|
||||
Run from `frontends/nextjs/`.
|
||||
|
||||
Run the full CI pipeline locally using act to validate changes before pushing.
|
||||
|
||||
```bash
|
||||
npm run act
|
||||
```
|
||||
|
||||
If specific jobs fail, debug with:
|
||||
- `npm run act:lint` - ESLint only
|
||||
- `npm run act:typecheck` - TypeScript validation
|
||||
- `npm run act:build` - Production build
|
||||
- `npm run act:e2e` - End-to-end tests
|
||||
|
||||
Use `npm run act:diagnose` to check setup issues without Docker.
|
||||
# Run GitHub Actions Locally
|
||||
|
||||
Run from `frontends/nextjs/`.
|
||||
|
||||
Run the full CI pipeline locally using act to validate changes before pushing.
|
||||
|
||||
```bash
|
||||
npm run act
|
||||
```
|
||||
|
||||
If specific jobs fail, debug with:
|
||||
- `npm run act:lint` - ESLint only
|
||||
- `npm run act:typecheck` - TypeScript validation
|
||||
- `npm run act:build` - Production build
|
||||
- `npm run act:e2e` - End-to-end tests
|
||||
|
||||
Use `npm run act:diagnose` to check setup issues without Docker.
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
# Deploy Application
|
||||
|
||||
Deploy MetaBuilder to production:
|
||||
|
||||
## Pre-Deployment Checks (from `frontends/nextjs/`)
|
||||
```bash
|
||||
npm run act # Full CI locally
|
||||
npm run build # Verify build succeeds
|
||||
npm run typecheck # No type errors
|
||||
```
|
||||
|
||||
## Docker Deployment (from repo root)
|
||||
```bash
|
||||
# Development
|
||||
docker-compose -f deployment/docker-compose.development.yml up
|
||||
|
||||
# Production
|
||||
docker-compose -f deployment/docker-compose.production.yml up -d
|
||||
```
|
||||
|
||||
## Database Migration (from `frontends/nextjs/`)
|
||||
```bash
|
||||
npm run db:migrate # Apply migrations
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
Required in production:
|
||||
- `DATABASE_URL` - Database connection string
|
||||
- `NODE_ENV=production`
|
||||
|
||||
## Post-Deployment
|
||||
1. Verify health endpoints
|
||||
2. Check logs for errors
|
||||
3. Test critical user flows
|
||||
4. Monitor tenant isolation working correctly
|
||||
# Deploy Application
|
||||
|
||||
Deploy MetaBuilder to production:
|
||||
|
||||
## Pre-Deployment Checks (from `frontends/nextjs/`)
|
||||
```bash
|
||||
npm run act # Full CI locally
|
||||
npm run build # Verify build succeeds
|
||||
npm run typecheck # No type errors
|
||||
```
|
||||
|
||||
## Docker Deployment (from repo root)
|
||||
```bash
|
||||
# Development
|
||||
docker-compose -f deployment/docker-compose.development.yml up
|
||||
|
||||
# Production
|
||||
docker-compose -f deployment/docker-compose.production.yml up -d
|
||||
```
|
||||
|
||||
## Database Migration (from `frontends/nextjs/`)
|
||||
```bash
|
||||
npm run db:migrate # Apply migrations
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
Required in production:
|
||||
- `DATABASE_URL` - Database connection string
|
||||
- `NODE_ENV=production`
|
||||
|
||||
## Post-Deployment
|
||||
1. Verify health endpoints
|
||||
2. Check logs for errors
|
||||
3. Test critical user flows
|
||||
4. Monitor tenant isolation working correctly
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# Database Query Pattern
|
||||
|
||||
Always use the `Database` class wrapper, never raw Prisma:
|
||||
|
||||
Run app commands from `frontends/nextjs/`.
|
||||
|
||||
```typescript
|
||||
// ✅ Correct - with tenant isolation
|
||||
const users = await Database.getUsers({ tenantId: user.tenantId })
|
||||
await Database.setSchemas(schemas, { tenantId })
|
||||
|
||||
// ❌ Wrong - raw Prisma, no tenant filter
|
||||
const users = await prisma.user.findMany()
|
||||
```
|
||||
|
||||
After schema changes in `prisma/schema.prisma`:
|
||||
```bash
|
||||
npm run db:generate # Regenerate Prisma client
|
||||
npm run db:push # Push to database
|
||||
```
|
||||
|
||||
Key file: `frontends/nextjs/src/lib/database.ts`
|
||||
# Database Query Pattern
|
||||
|
||||
Always use the `Database` class wrapper, never raw Prisma:
|
||||
|
||||
Run app commands from `frontends/nextjs/`.
|
||||
|
||||
```typescript
|
||||
// ✅ Correct - with tenant isolation
|
||||
const users = await Database.getUsers({ tenantId: user.tenantId })
|
||||
await Database.setSchemas(schemas, { tenantId })
|
||||
|
||||
// ❌ Wrong - raw Prisma, no tenant filter
|
||||
const users = await prisma.user.findMany()
|
||||
```
|
||||
|
||||
After schema changes in `prisma/schema.prisma`:
|
||||
```bash
|
||||
npm run db:generate # Regenerate Prisma client
|
||||
npm run db:push # Push to database
|
||||
```
|
||||
|
||||
Key file: `frontends/nextjs/src/lib/database.ts`
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
# Add DBAL Entity
|
||||
|
||||
Run DBAL commands from `dbal/`.
|
||||
|
||||
Add a new entity to the DBAL following the API-first approach:
|
||||
|
||||
1. **Define entity** in `dbal/shared/api/schema/entities/{name}.yaml`:
|
||||
```yaml
|
||||
entity: EntityName
|
||||
version: "1.0"
|
||||
fields:
|
||||
id: { type: uuid, primary: true, generated: true }
|
||||
# Add fields...
|
||||
```
|
||||
|
||||
2. **Define operations** in `dbal/shared/api/schema/operations/{name}.ops.yaml`
|
||||
|
||||
3. **Generate types**: `python tools/codegen/gen_types.py`
|
||||
|
||||
4. **Implement adapters** in both:
|
||||
- `dbal/development/src/adapters/`
|
||||
- `dbal/production/src/adapters/`
|
||||
|
||||
5. **Add conformance tests** in `dbal/shared/common/contracts/{name}_tests.yaml`
|
||||
|
||||
6. **Verify**: `python tools/conformance/run_all.py`
|
||||
# Add DBAL Entity
|
||||
|
||||
Run DBAL commands from `dbal/`.
|
||||
|
||||
Add a new entity to the DBAL following the API-first approach:
|
||||
|
||||
1. **Define entity** in `dbal/shared/api/schema/entities/{name}.yaml`:
|
||||
```yaml
|
||||
entity: EntityName
|
||||
version: "1.0"
|
||||
fields:
|
||||
id: { type: uuid, primary: true, generated: true }
|
||||
# Add fields...
|
||||
```
|
||||
|
||||
2. **Define operations** in `dbal/shared/api/schema/operations/{name}.ops.yaml`
|
||||
|
||||
3. **Generate types**: `python tools/codegen/gen_types.py`
|
||||
|
||||
4. **Implement adapters** in both:
|
||||
- `dbal/development/src/adapters/`
|
||||
- `dbal/production/src/adapters/`
|
||||
|
||||
5. **Add conformance tests** in `dbal/shared/common/contracts/{name}_tests.yaml`
|
||||
|
||||
6. **Verify**: `python tools/conformance/run_all.py`
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
# Write Lua Business Logic
|
||||
|
||||
Add business logic as a sandboxed Lua script:
|
||||
|
||||
## Create Script
|
||||
Location: `packages/{pkg}/seed/scripts/` or `src/lib/lua-snippets.ts`
|
||||
|
||||
```lua
|
||||
-- Sandbox restrictions: NO os, io, require, loadfile
|
||||
function validateInput(value)
|
||||
if not value or value == "" then
|
||||
return false, "Value required"
|
||||
end
|
||||
return true, nil
|
||||
end
|
||||
```
|
||||
|
||||
## Register Script
|
||||
```typescript
|
||||
renderer.registerLuaScript('validate_input', {
|
||||
code: luaCode,
|
||||
parameters: [{ name: 'value', type: 'string' }],
|
||||
returnType: 'boolean'
|
||||
})
|
||||
```
|
||||
|
||||
## Execute Script
|
||||
```typescript
|
||||
const result = await renderer.executeLuaScript('validate_input', [userInput])
|
||||
```
|
||||
|
||||
## When to Use Lua
|
||||
- Validation rules
|
||||
- Data transformation
|
||||
- Conditional rendering logic
|
||||
- Business rules that change frequently
|
||||
# Write Lua Business Logic
|
||||
|
||||
Add business logic as a sandboxed Lua script:
|
||||
|
||||
## Create Script
|
||||
Location: `packages/{pkg}/seed/scripts/` or `src/lib/lua-snippets.ts`
|
||||
|
||||
```lua
|
||||
-- Sandbox restrictions: NO os, io, require, loadfile
|
||||
function validateInput(value)
|
||||
if not value or value == "" then
|
||||
return false, "Value required"
|
||||
end
|
||||
return true, nil
|
||||
end
|
||||
```
|
||||
|
||||
## Register Script
|
||||
```typescript
|
||||
renderer.registerLuaScript('validate_input', {
|
||||
code: luaCode,
|
||||
parameters: [{ name: 'value', type: 'string' }],
|
||||
returnType: 'boolean'
|
||||
})
|
||||
```
|
||||
|
||||
## Execute Script
|
||||
```typescript
|
||||
const result = await renderer.executeLuaScript('validate_input', [userInput])
|
||||
```
|
||||
|
||||
## When to Use Lua
|
||||
- Validation rules
|
||||
- Data transformation
|
||||
- Conditional rendering logic
|
||||
- Business rules that change frequently
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
# Add Database Migration
|
||||
|
||||
Add or modify database schema:
|
||||
|
||||
Run app commands from `frontends/nextjs/` unless a step says otherwise.
|
||||
|
||||
## 1. Update Schema
|
||||
Edit `prisma/schema.prisma`:
|
||||
```prisma
|
||||
model NewEntity {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
tenantId String // Required for multi-tenancy
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
createdAt BigInt
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Generate & Apply
|
||||
```bash
|
||||
npm run db:generate # Update Prisma client
|
||||
npm run db:push # Push to dev database
|
||||
# OR for production:
|
||||
npx prisma migrate dev --name describe_change
|
||||
npm run db:migrate # Apply in production
|
||||
```
|
||||
|
||||
## 3. Add Database Wrapper Methods
|
||||
In `src/lib/database.ts`:
|
||||
```typescript
|
||||
static async getNewEntities(filter: { tenantId: string }) {
|
||||
return prisma.newEntity.findMany({
|
||||
where: { tenantId: filter.tenantId }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Update DBAL (if applicable)
|
||||
Add entity to `dbal/shared/api/schema/entities/`
|
||||
# Add Database Migration
|
||||
|
||||
Add or modify database schema:
|
||||
|
||||
Run app commands from `frontends/nextjs/` unless a step says otherwise.
|
||||
|
||||
## 1. Update Schema
|
||||
Edit `prisma/schema.prisma`:
|
||||
```prisma
|
||||
model NewEntity {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
tenantId String // Required for multi-tenancy
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
createdAt BigInt
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Generate & Apply
|
||||
```bash
|
||||
npm run db:generate # Update Prisma client
|
||||
npm run db:push # Push to dev database
|
||||
# OR for production:
|
||||
npx prisma migrate dev --name describe_change
|
||||
npm run db:migrate # Apply in production
|
||||
```
|
||||
|
||||
## 3. Add Database Wrapper Methods
|
||||
In `src/lib/database.ts`:
|
||||
```typescript
|
||||
static async getNewEntities(filter: { tenantId: string }) {
|
||||
return prisma.newEntity.findMany({
|
||||
where: { tenantId: filter.tenantId }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Update DBAL (if applicable)
|
||||
Add entity to `dbal/shared/api/schema/entities/`
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
# Add Declarative Component
|
||||
|
||||
Add a new component using the declarative pattern (not hardcoded TSX):
|
||||
|
||||
1. **Define in package** `packages/{pkg}/seed/components.json`:
|
||||
```json
|
||||
{
|
||||
"type": "MyComponent",
|
||||
"category": "ui",
|
||||
"label": "My Component",
|
||||
"props": [
|
||||
{ "name": "title", "type": "string", "required": true }
|
||||
],
|
||||
"config": {
|
||||
"layout": "vertical",
|
||||
"styling": { "className": "myComponentRoot" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: `styling.className` should reference a real CSS class (SCSS/modules), not Tailwind utility classes.
|
||||
|
||||
2. **Register** via `DeclarativeComponentRenderer.registerComponentConfig()`
|
||||
|
||||
3. **Render** using `<RenderComponent component={...} />`
|
||||
|
||||
Keep components under 150 LOC. Use composition for complex UIs.
|
||||
# Add Declarative Component
|
||||
|
||||
Add a new component using the declarative pattern (not hardcoded TSX):
|
||||
|
||||
1. **Define in package** `packages/{pkg}/seed/components.json`:
|
||||
```json
|
||||
{
|
||||
"type": "MyComponent",
|
||||
"category": "ui",
|
||||
"label": "My Component",
|
||||
"props": [
|
||||
{ "name": "title", "type": "string", "required": true }
|
||||
],
|
||||
"config": {
|
||||
"layout": "vertical",
|
||||
"styling": { "className": "myComponentRoot" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: `styling.className` should reference a real CSS class (SCSS/modules), not Tailwind utility classes.
|
||||
|
||||
2. **Register** via `DeclarativeComponentRenderer.registerComponentConfig()`
|
||||
|
||||
3. **Render** using `<RenderComponent component={...} />`
|
||||
|
||||
Keep components under 150 LOC. Use composition for complex UIs.
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
# Implement Feature
|
||||
|
||||
Implement following MetaBuilder conventions:
|
||||
|
||||
Run app commands from `frontends/nextjs/` unless a step says otherwise.
|
||||
|
||||
## Implementation Order
|
||||
1. **Schema first**: Update `prisma/schema.prisma` if needed
|
||||
```bash
|
||||
npm run db:generate && npm run db:push
|
||||
```
|
||||
|
||||
2. **DBAL contracts**: If new entity/operation, update YAML in `dbal/shared/api/schema/`
|
||||
|
||||
3. **Database layer**: Add methods to `Database` class in `src/lib/database.ts`
|
||||
|
||||
4. **Business logic**:
|
||||
- Simple validation → Lua script
|
||||
- Complex logic → TypeScript in `src/lib/`
|
||||
|
||||
5. **UI components**:
|
||||
- Declarative → `packages/*/seed/components.json`
|
||||
- React → `src/components/` (< 150 LOC)
|
||||
|
||||
6. **Tests**: Parameterized tests next to source files
|
||||
|
||||
## Checklist
|
||||
- [ ] tenantId filtering on all queries
|
||||
- [ ] Permission level check
|
||||
- [ ] Component under 150 LOC
|
||||
- [ ] No hardcoded values (use DB/config)
|
||||
- [ ] Tests with `it.each()` pattern
|
||||
# Implement Feature
|
||||
|
||||
Implement following MetaBuilder conventions:
|
||||
|
||||
Run app commands from `frontends/nextjs/` unless a step says otherwise.
|
||||
|
||||
## Implementation Order
|
||||
1. **Schema first**: Update `prisma/schema.prisma` if needed
|
||||
```bash
|
||||
npm run db:generate && npm run db:push
|
||||
```
|
||||
|
||||
2. **DBAL contracts**: If new entity/operation, update YAML in `dbal/shared/api/schema/`
|
||||
|
||||
3. **Database layer**: Add methods to `Database` class in `src/lib/database.ts`
|
||||
|
||||
4. **Business logic**:
|
||||
- Simple validation → Lua script
|
||||
- Complex logic → TypeScript in `src/lib/`
|
||||
|
||||
5. **UI components**:
|
||||
- Declarative → `packages/*/seed/components.json`
|
||||
- React → `src/components/` (< 150 LOC)
|
||||
|
||||
6. **Tests**: Parameterized tests next to source files
|
||||
|
||||
## Checklist
|
||||
- [ ] tenantId filtering on all queries
|
||||
- [ ] Permission level check
|
||||
- [ ] Component under 150 LOC
|
||||
- [ ] No hardcoded values (use DB/config)
|
||||
- [ ] Tests with `it.each()` pattern
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
# Create New Package
|
||||
|
||||
Create a new MetaBuilder package with the standard structure:
|
||||
|
||||
```
|
||||
packages/{name}/
|
||||
├── seed/
|
||||
│ ├── metadata.json # Package info, version, dependencies
|
||||
│ ├── components.json # Component definitions
|
||||
│ └── scripts/ # Lua scripts (optional)
|
||||
├── static_content/ # Assets (optional)
|
||||
└── tests/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
Required metadata.json format:
|
||||
```json
|
||||
{
|
||||
"packageId": "{name}",
|
||||
"name": "Display Name",
|
||||
"version": "1.0.0",
|
||||
"description": "Package description",
|
||||
"author": "MetaBuilder",
|
||||
"category": "ui",
|
||||
"dependencies": [],
|
||||
"exports": { "components": [] }
|
||||
}
|
||||
```
|
||||
# Create New Package
|
||||
|
||||
Create a new MetaBuilder package with the standard structure:
|
||||
|
||||
```
|
||||
packages/{name}/
|
||||
├── seed/
|
||||
│ ├── metadata.json # Package info, version, dependencies
|
||||
│ ├── components.json # Component definitions
|
||||
│ └── scripts/ # Lua scripts (optional)
|
||||
├── static_content/ # Assets (optional)
|
||||
└── tests/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
Required metadata.json format:
|
||||
```json
|
||||
{
|
||||
"packageId": "{name}",
|
||||
"name": "Display Name",
|
||||
"version": "1.0.0",
|
||||
"description": "Package description",
|
||||
"author": "MetaBuilder",
|
||||
"category": "ui",
|
||||
"dependencies": [],
|
||||
"exports": { "components": [] }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
# Debug Issue
|
||||
|
||||
Systematic debugging approach for MetaBuilder:
|
||||
|
||||
Run app commands from `frontends/nextjs/`. Run DBAL conformance from `dbal/`.
|
||||
|
||||
## 1. Identify Layer
|
||||
- **UI**: Check browser console, React DevTools
|
||||
- **API/Data**: Check `Database` class calls
|
||||
- **DBAL**: Check YAML schema matches implementation
|
||||
- **Lua**: Check sandbox execution logs
|
||||
|
||||
## 2. Common Issues
|
||||
|
||||
### "Cannot read property" in component
|
||||
→ Check if data query includes `tenantId`
|
||||
|
||||
### Type errors after schema change
|
||||
```bash
|
||||
npm run db:generate # Regenerate Prisma types
|
||||
```
|
||||
|
||||
### DBAL TypeScript/C++ divergence
|
||||
```bash
|
||||
python tools/conformance/run_all.py # Find which test fails
|
||||
```
|
||||
|
||||
### Lua script fails silently
|
||||
→ Check for forbidden APIs: `os`, `io`, `require`, `loadfile`
|
||||
|
||||
## 3. Logging
|
||||
```typescript
|
||||
// Database queries
|
||||
console.log('[DB]', query, { tenantId })
|
||||
|
||||
// Lua execution
|
||||
const result = await renderer.executeLuaScript(id, params)
|
||||
console.log('[Lua]', { result, logs: result.logs })
|
||||
```
|
||||
|
||||
## 4. Test in Isolation
|
||||
```bash
|
||||
npm run test:unit -- path/to/test.ts
|
||||
```
|
||||
# Debug Issue
|
||||
|
||||
Systematic debugging approach for MetaBuilder:
|
||||
|
||||
Run app commands from `frontends/nextjs/`. Run DBAL conformance from `dbal/`.
|
||||
|
||||
## 1. Identify Layer
|
||||
- **UI**: Check browser console, React DevTools
|
||||
- **API/Data**: Check `Database` class calls
|
||||
- **DBAL**: Check YAML schema matches implementation
|
||||
- **Lua**: Check sandbox execution logs
|
||||
|
||||
## 2. Common Issues
|
||||
|
||||
### "Cannot read property" in component
|
||||
→ Check if data query includes `tenantId`
|
||||
|
||||
### Type errors after schema change
|
||||
```bash
|
||||
npm run db:generate # Regenerate Prisma types
|
||||
```
|
||||
|
||||
### DBAL TypeScript/C++ divergence
|
||||
```bash
|
||||
python tools/conformance/run_all.py # Find which test fails
|
||||
```
|
||||
|
||||
### Lua script fails silently
|
||||
→ Check for forbidden APIs: `os`, `io`, `require`, `loadfile`
|
||||
|
||||
## 3. Logging
|
||||
```typescript
|
||||
// Database queries
|
||||
console.log('[DB]', query, { tenantId })
|
||||
|
||||
// Lua execution
|
||||
const result = await renderer.executeLuaScript(id, params)
|
||||
console.log('[Lua]', { result, logs: result.logs })
|
||||
```
|
||||
|
||||
## 4. Test in Isolation
|
||||
```bash
|
||||
npm run test:unit -- path/to/test.ts
|
||||
```
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
# Performance Optimization
|
||||
|
||||
Optimize MetaBuilder performance:
|
||||
|
||||
Run performance scripts from `frontends/nextjs/` after `npm run build` (requires `tsx` via `npx`).
|
||||
|
||||
## Identify Bottlenecks
|
||||
```bash
|
||||
npx tsx ../../tools/analyze-render-performance.ts
|
||||
npx tsx ../../tools/analyze-bundle-size.ts
|
||||
npx tsx ../../tools/check-performance-budget.ts
|
||||
```
|
||||
|
||||
## Common Optimizations
|
||||
|
||||
### 1. Database Queries
|
||||
```typescript
|
||||
// ❌ N+1 query
|
||||
for (const user of users) {
|
||||
const tenant = await Database.getTenant(user.tenantId)
|
||||
}
|
||||
|
||||
// ✅ Batch query
|
||||
const users = await Database.getUsersWithTenants({ tenantId })
|
||||
```
|
||||
|
||||
### 2. Component Rendering
|
||||
```tsx
|
||||
// ❌ Re-renders on every parent render
|
||||
function List({ items }) {
|
||||
return items.map(item => <Item key={item.id} {...item} />)
|
||||
}
|
||||
|
||||
// ✅ Memoized
|
||||
const MemoizedItem = React.memo(Item)
|
||||
function List({ items }) {
|
||||
return items.map(item => <MemoizedItem key={item.id} {...item} />)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Bundle Size
|
||||
- Use dynamic imports for large components
|
||||
- Check `docs/reports/size-limits-report.json`
|
||||
|
||||
### 4. Lua Script Caching
|
||||
Scripts are compiled once - avoid registering repeatedly
|
||||
# Performance Optimization
|
||||
|
||||
Optimize MetaBuilder performance:
|
||||
|
||||
Run performance scripts from `frontends/nextjs/` after `npm run build` (requires `tsx` via `npx`).
|
||||
|
||||
## Identify Bottlenecks
|
||||
```bash
|
||||
npx tsx ../../tools/analyze-render-performance.ts
|
||||
npx tsx ../../tools/analyze-bundle-size.ts
|
||||
npx tsx ../../tools/check-performance-budget.ts
|
||||
```
|
||||
|
||||
## Common Optimizations
|
||||
|
||||
### 1. Database Queries
|
||||
```typescript
|
||||
// ❌ N+1 query
|
||||
for (const user of users) {
|
||||
const tenant = await Database.getTenant(user.tenantId)
|
||||
}
|
||||
|
||||
// ✅ Batch query
|
||||
const users = await Database.getUsersWithTenants({ tenantId })
|
||||
```
|
||||
|
||||
### 2. Component Rendering
|
||||
```tsx
|
||||
// ❌ Re-renders on every parent render
|
||||
function List({ items }) {
|
||||
return items.map(item => <Item key={item.id} {...item} />)
|
||||
}
|
||||
|
||||
// ✅ Memoized
|
||||
const MemoizedItem = React.memo(Item)
|
||||
function List({ items }) {
|
||||
return items.map(item => <MemoizedItem key={item.id} {...item} />)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Bundle Size
|
||||
- Use dynamic imports for large components
|
||||
- Check `docs/reports/size-limits-report.json`
|
||||
|
||||
### 4. Lua Script Caching
|
||||
Scripts are compiled once - avoid registering repeatedly
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
# Refactor Large Component
|
||||
|
||||
Break down a component exceeding 150 LOC:
|
||||
|
||||
## 1. Identify Split Points
|
||||
- Separate data fetching from rendering
|
||||
- Extract repeated patterns into sub-components
|
||||
- Move business logic to Lua or utility functions
|
||||
|
||||
## 2. Refactoring Patterns
|
||||
|
||||
### Extract Child Components
|
||||
```tsx
|
||||
// Before: 200 LOC monolith
|
||||
function BigComponent() { /* everything */ }
|
||||
|
||||
// After: Composed
|
||||
function BigComponent() {
|
||||
return (
|
||||
<Container>
|
||||
<Header />
|
||||
<ContentList items={items} />
|
||||
<Footer />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Convert to Declarative
|
||||
```tsx
|
||||
// Before: Hardcoded
|
||||
<UserForm user={user} />
|
||||
|
||||
// After: Declarative
|
||||
<RenderComponent component={{
|
||||
type: 'form',
|
||||
props: { schema: formSchema }
|
||||
}} />
|
||||
```
|
||||
|
||||
### Extract Hooks
|
||||
```typescript
|
||||
// Custom hook for data logic
|
||||
function useUserData(tenantId: string) {
|
||||
const [users, setUsers] = useState([])
|
||||
// ... fetch logic
|
||||
return { users, loading, error }
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Verify
|
||||
- Each file < 150 LOC
|
||||
- Tests still pass
|
||||
- No functionality lost
|
||||
# Refactor Large Component
|
||||
|
||||
Break down a component exceeding 150 LOC:
|
||||
|
||||
## 1. Identify Split Points
|
||||
- Separate data fetching from rendering
|
||||
- Extract repeated patterns into sub-components
|
||||
- Move business logic to Lua or utility functions
|
||||
|
||||
## 2. Refactoring Patterns
|
||||
|
||||
### Extract Child Components
|
||||
```tsx
|
||||
// Before: 200 LOC monolith
|
||||
function BigComponent() { /* everything */ }
|
||||
|
||||
// After: Composed
|
||||
function BigComponent() {
|
||||
return (
|
||||
<Container>
|
||||
<Header />
|
||||
<ContentList items={items} />
|
||||
<Footer />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Convert to Declarative
|
||||
```tsx
|
||||
// Before: Hardcoded
|
||||
<UserForm user={user} />
|
||||
|
||||
// After: Declarative
|
||||
<RenderComponent component={{
|
||||
type: 'form',
|
||||
props: { schema: formSchema }
|
||||
}} />
|
||||
```
|
||||
|
||||
### Extract Hooks
|
||||
```typescript
|
||||
// Custom hook for data logic
|
||||
function useUserData(tenantId: string) {
|
||||
const [users, setUsers] = useState([])
|
||||
// ... fetch logic
|
||||
return { users, loading, error }
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Verify
|
||||
- Each file < 150 LOC
|
||||
- Tests still pass
|
||||
- No functionality lost
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
# Fix Security Issue
|
||||
|
||||
Address security vulnerabilities in MetaBuilder:
|
||||
|
||||
Run app commands from `frontends/nextjs/`.
|
||||
|
||||
## Common Security Fixes
|
||||
|
||||
### 1. Missing Tenant Isolation
|
||||
```typescript
|
||||
// ❌ Vulnerable
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Fixed
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
### 2. Permission Bypass
|
||||
```typescript
|
||||
// ❌ Missing check
|
||||
async function adminAction() { /* ... */ }
|
||||
|
||||
// ✅ With check
|
||||
async function adminAction(user: User) {
|
||||
if (user.level < 3) throw new Error('Admin required')
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Lua Sandbox Escape
|
||||
```lua
|
||||
-- ❌ Never allow these in Lua scripts
|
||||
os.execute()
|
||||
io.open()
|
||||
require()
|
||||
loadfile()
|
||||
|
||||
-- ✅ Sandbox enforces restrictions automatically
|
||||
```
|
||||
|
||||
### 4. Raw SQL/Prisma
|
||||
```typescript
|
||||
// ❌ Bypass Database wrapper
|
||||
prisma.$queryRaw`SELECT * FROM users`
|
||||
|
||||
// ✅ Use Database class
|
||||
Database.getUsers({ tenantId })
|
||||
```
|
||||
|
||||
## Security Scan
|
||||
```bash
|
||||
npm audit
|
||||
npm run test:unit -- src/lib/security/security-scanner.test.ts
|
||||
```
|
||||
# Fix Security Issue
|
||||
|
||||
Address security vulnerabilities in MetaBuilder:
|
||||
|
||||
Run app commands from `frontends/nextjs/`.
|
||||
|
||||
## Common Security Fixes
|
||||
|
||||
### 1. Missing Tenant Isolation
|
||||
```typescript
|
||||
// ❌ Vulnerable
|
||||
const data = await Database.getData()
|
||||
|
||||
// ✅ Fixed
|
||||
const data = await Database.getData({ tenantId: user.tenantId })
|
||||
```
|
||||
|
||||
### 2. Permission Bypass
|
||||
```typescript
|
||||
// ❌ Missing check
|
||||
async function adminAction() { /* ... */ }
|
||||
|
||||
// ✅ With check
|
||||
async function adminAction(user: User) {
|
||||
if (user.level < 3) throw new Error('Admin required')
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Lua Sandbox Escape
|
||||
```lua
|
||||
-- ❌ Never allow these in Lua scripts
|
||||
os.execute()
|
||||
io.open()
|
||||
require()
|
||||
loadfile()
|
||||
|
||||
-- ✅ Sandbox enforces restrictions automatically
|
||||
```
|
||||
|
||||
### 4. Raw SQL/Prisma
|
||||
```typescript
|
||||
// ❌ Bypass Database wrapper
|
||||
prisma.$queryRaw`SELECT * FROM users`
|
||||
|
||||
// ✅ Use Database class
|
||||
Database.getUsers({ tenantId })
|
||||
```
|
||||
|
||||
## Security Scan
|
||||
```bash
|
||||
npm audit
|
||||
npm run test:unit -- src/lib/security/security-scanner.test.ts
|
||||
```
|
||||
|
||||
6
.github/prompts/misc/EEK-STUCK.md
vendored
6
.github/prompts/misc/EEK-STUCK.md
vendored
@@ -1,3 +1,3 @@
|
||||
Make it up as you go along using prompt as guide.
|
||||
|
||||
Go through codebase and read docs and code, write some TODO statements.
|
||||
Make it up as you go along using prompt as guide.
|
||||
|
||||
Go through codebase and read docs and code, write some TODO statements.
|
||||
|
||||
2
.github/prompts/misc/LAMBDA_PROMPT.md
vendored
2
.github/prompts/misc/LAMBDA_PROMPT.md
vendored
@@ -1 +1 @@
|
||||
Make entire project so its 1 lambda/function per file, then make a class that wraps a bunch of lambdas. This solves the awkward code length problem.
|
||||
Make entire project so its 1 lambda/function per file, then make a class that wraps a bunch of lambdas. This solves the awkward code length problem.
|
||||
|
||||
76
.github/prompts/test/4-test-run.prompt.md
vendored
76
.github/prompts/test/4-test-run.prompt.md
vendored
@@ -1,38 +1,38 @@
|
||||
# Run All Tests
|
||||
|
||||
Run app tests from `frontends/nextjs/`. Run DBAL conformance from `dbal/`.
|
||||
|
||||
Execute the full test suite:
|
||||
|
||||
## Unit Tests
|
||||
```bash
|
||||
npm run test:unit # Single run
|
||||
npm run test # Watch mode
|
||||
npm run test:coverage # With coverage
|
||||
npm run test:coverage:report # Generate markdown report
|
||||
```
|
||||
|
||||
## End-to-End Tests
|
||||
```bash
|
||||
npm run test:e2e # Headless
|
||||
npm run test:e2e:headed # With browser
|
||||
npm run test:e2e:ui # Interactive UI
|
||||
```
|
||||
|
||||
## Full CI Pipeline (Local)
|
||||
```bash
|
||||
npm run act # Full pipeline
|
||||
npm run act:diagnose # Check setup
|
||||
```
|
||||
|
||||
## Specific Checks
|
||||
```bash
|
||||
npm run lint # ESLint
|
||||
npm run typecheck # TypeScript
|
||||
npm run test:check-functions # Function coverage
|
||||
```
|
||||
|
||||
## DBAL Conformance (from `dbal/`)
|
||||
```bash
|
||||
python tools/conformance/run_all.py
|
||||
```
|
||||
# Run All Tests
|
||||
|
||||
Run app tests from `frontends/nextjs/`. Run DBAL conformance from `dbal/`.
|
||||
|
||||
Execute the full test suite:
|
||||
|
||||
## Unit Tests
|
||||
```bash
|
||||
npm run test:unit # Single run
|
||||
npm run test # Watch mode
|
||||
npm run test:coverage # With coverage
|
||||
npm run test:coverage:report # Generate markdown report
|
||||
```
|
||||
|
||||
## End-to-End Tests
|
||||
```bash
|
||||
npm run test:e2e # Headless
|
||||
npm run test:e2e:headed # With browser
|
||||
npm run test:e2e:ui # Interactive UI
|
||||
```
|
||||
|
||||
## Full CI Pipeline (Local)
|
||||
```bash
|
||||
npm run act # Full pipeline
|
||||
npm run act:diagnose # Check setup
|
||||
```
|
||||
|
||||
## Specific Checks
|
||||
```bash
|
||||
npm run lint # ESLint
|
||||
npm run typecheck # TypeScript
|
||||
npm run test:check-functions # Function coverage
|
||||
```
|
||||
|
||||
## DBAL Conformance (from `dbal/`)
|
||||
```bash
|
||||
python tools/conformance/run_all.py
|
||||
```
|
||||
|
||||
52
.github/prompts/test/4-test-write.prompt.md
vendored
52
.github/prompts/test/4-test-write.prompt.md
vendored
@@ -1,26 +1,26 @@
|
||||
# Write Parameterized Tests
|
||||
|
||||
Run tests from `frontends/nextjs/`.
|
||||
|
||||
Add tests using the parameterized `it.each()` pattern:
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
describe('myFunction', () => {
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
{ input: 'edge-case', expected: 'handled' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Place test files next to source: `utils.ts` → `utils.test.ts`
|
||||
|
||||
Run tests:
|
||||
- `npm test` - Watch mode
|
||||
- `npm run test:unit` - Single run
|
||||
- `npm run test:coverage:report` - Generate coverage markdown
|
||||
# Write Parameterized Tests
|
||||
|
||||
Run tests from `frontends/nextjs/`.
|
||||
|
||||
Add tests using the parameterized `it.each()` pattern:
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
describe('myFunction', () => {
|
||||
it.each([
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
{ input: 'edge-case', expected: 'handled' },
|
||||
])('should handle $input', ({ input, expected }) => {
|
||||
expect(myFunction(input)).toBe(expected)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Place test files next to source: `utils.ts` → `utils.test.ts`
|
||||
|
||||
Run tests:
|
||||
- `npm test` - Watch mode
|
||||
- `npm run test:unit` - Single run
|
||||
- `npm run test:coverage:report` - Generate coverage markdown
|
||||
|
||||
142
.github/prompts/workflow/0-kickstart.md
vendored
142
.github/prompts/workflow/0-kickstart.md
vendored
@@ -1,71 +1,71 @@
|
||||
# Kickstart
|
||||
|
||||
Use this as the default workflow when starting work in this repo.
|
||||
|
||||
## Workflow
|
||||
1. Skim `docs/START_HERE.md` (if new), `docs/INDEX.md`, and relevant items in `docs/todo/`.
|
||||
2. Check for scoped rules in nested `AGENTS.md` files (e.g. `dbal/docs/AGENTS.md`) before editing those areas.
|
||||
3. Use the prompts in `.github/prompts/` as needed:
|
||||
- Plan: `1-plan-feature.prompt.md`
|
||||
- Design: `2-design-component.prompt.md`
|
||||
- Implement: `3-impl-*.prompt.md`
|
||||
- Test: `4-test-*.prompt.md`
|
||||
- Review: `5-review-code.prompt.md`
|
||||
- Deploy: `6-deploy-*.prompt.md`
|
||||
- Maintain: `7-maintain-*.prompt.md`
|
||||
- Docs: `8-docs-feature.prompt.md`
|
||||
4. Keep changes small and follow existing patterns; avoid dependency churn.
|
||||
|
||||
## Where Work Lives
|
||||
- Next.js app: `frontends/nextjs/` (source in `src/`, E2E in `e2e/`, local scripts in `scripts/`).
|
||||
- Component packages: `packages/` (seed JSON under `packages/*/seed/`, optional `static_content/`, schema checks in `packages/*/tests/`).
|
||||
- DBAL: `dbal/` (TypeScript library in `dbal/development/`).
|
||||
- Prisma schema/migrations: `prisma/` (`schema.prisma`, `migrations/`).
|
||||
- Shared config: `config/` (symlinked into `frontends/nextjs/`).
|
||||
- Repo utilities: `tools/` (quality checks, workflow helpers, code analysis).
|
||||
|
||||
## Common Commands
|
||||
Run app workflows from `frontends/nextjs/`:
|
||||
- Install: `npm ci` (or `npm install`)
|
||||
- Dev: `npm run dev`
|
||||
- Build/serve: `npm run build` / `npm run start`
|
||||
- Lint: `npm run lint` / `npm run lint:fix`
|
||||
- Typecheck: `npm run typecheck`
|
||||
- Unit: `npm run test:unit` / `npm run test:coverage`
|
||||
- Function coverage: `npm run test:check-functions`
|
||||
- Coverage report: `npm run test:coverage:report`
|
||||
- E2E: `npm run test:e2e`
|
||||
- Prisma (schema in `prisma/schema.prisma`, config in `frontends/nextjs/prisma.config.ts`):
|
||||
- First-time setup: copy `.env.example` to `.env` (or ensure `DATABASE_URL` is set)
|
||||
- Commands: `npm run db:generate` / `npm run db:push` / `npm run db:migrate`
|
||||
- Validate: `npx prisma validate`
|
||||
- Coverage output: `frontends/nextjs/coverage/`
|
||||
|
||||
DBAL workflows live in `dbal/development/` (`npm run build`, `npm run test:unit`).
|
||||
|
||||
## Source + Tests
|
||||
- TypeScript + ESM. Prefer `@/…` imports inside `frontends/nextjs/src/`.
|
||||
- React components: `PascalCase.tsx`; hooks: `useThing.ts`; tests: `*.test.ts(x)`.
|
||||
- Unit tests: `frontends/nextjs/src/**/*.test.ts(x)` and `packages/*/tests/*.test.ts`; E2E: `frontends/nextjs/e2e/`.
|
||||
- Prefer one focused function (“lambda”) per file; use classes only as containers for related functions (see `.github/prompts/LAMBDA_PROMPT.md`).
|
||||
- Add/adjust tests with behavior changes; keep tests deterministic (no network, stable clocks/IDs), and parameterize where it improves coverage (`it.each()`); keep source↔test naming aligned.
|
||||
- Leave TODOs only when you’re explicitly deferring follow-up work (and include the next step).
|
||||
|
||||
## Git Hygiene
|
||||
- Commit as you go with descriptive (Conventional Commit-style) messages; default to trunk-based work on `main` unless a PR flow is required.
|
||||
- If multiple agents are working, merge/rebase carefully and avoid overwriting each other’s changes.
|
||||
- Before opening a PR, run `npm run lint`, `npm run typecheck`, and the relevant tests (from `frontends/nextjs/`).
|
||||
- PRs should include: what/why, linked issue (if any), screenshots for UI changes, and notes on DB/schema changes.
|
||||
|
||||
## Architecture Guardrails
|
||||
- Prefer data-driven config (JSON/Lua) over hard-coded TS/TSX; start with `packages/*/seed/` and `docs/architecture/data-driven-architecture.md`.
|
||||
- Prefer declarative UI via `RenderComponent` / generic renderers (see `docs/architecture/generic-page-system.md`).
|
||||
- Route data access through DBAL / the `Database` wrapper (`frontends/nextjs/src/lib/db/` or `@/lib/db`); don’t bypass it.
|
||||
- Assume multi-tenancy: include `tenantId` filtering and isolate per-tenant data.
|
||||
- UI uses Material UI (`@mui/*`) and SCSS/modules as needed; don’t introduce Radix UI or Tailwind. See `docs/RADIX_TO_MUI_MIGRATION.md` and `UI_STANDARDS.md`.
|
||||
- Package metadata: keep `packages/*/seed/metadata.json` `packageId` in `snake_case` and versions semver (e.g. `1.2.3`).
|
||||
|
||||
## CI / Workflows
|
||||
- Use `act` to reproduce and debug GitHub Actions locally (from `frontends/nextjs/`: `npm run act`, `npm run act:diagnose`; see `docs/guides/ACT_TESTING.md`).
|
||||
|
||||
If you get stuck, see `.github/prompts/EEK-STUCK.md`.
|
||||
# Kickstart
|
||||
|
||||
Use this as the default workflow when starting work in this repo.
|
||||
|
||||
## Workflow
|
||||
1. Skim `docs/START_HERE.md` (if new), `docs/INDEX.md`, and relevant items in `docs/todo/`.
|
||||
2. Check for scoped rules in nested `AGENTS.md` files (e.g. `dbal/docs/AGENTS.md`) before editing those areas.
|
||||
3. Use the prompts in `.github/prompts/` as needed:
|
||||
- Plan: `1-plan-feature.prompt.md`
|
||||
- Design: `2-design-component.prompt.md`
|
||||
- Implement: `3-impl-*.prompt.md`
|
||||
- Test: `4-test-*.prompt.md`
|
||||
- Review: `5-review-code.prompt.md`
|
||||
- Deploy: `6-deploy-*.prompt.md`
|
||||
- Maintain: `7-maintain-*.prompt.md`
|
||||
- Docs: `8-docs-feature.prompt.md`
|
||||
4. Keep changes small and follow existing patterns; avoid dependency churn.
|
||||
|
||||
## Where Work Lives
|
||||
- Next.js app: `frontends/nextjs/` (source in `src/`, E2E in `e2e/`, local scripts in `scripts/`).
|
||||
- Component packages: `packages/` (seed JSON under `packages/*/seed/`, optional `static_content/`, schema checks in `packages/*/tests/`).
|
||||
- DBAL: `dbal/` (TypeScript library in `dbal/development/`).
|
||||
- Prisma schema/migrations: `prisma/` (`schema.prisma`, `migrations/`).
|
||||
- Shared config: `config/` (symlinked into `frontends/nextjs/`).
|
||||
- Repo utilities: `tools/` (quality checks, workflow helpers, code analysis).
|
||||
|
||||
## Common Commands
|
||||
Run app workflows from `frontends/nextjs/`:
|
||||
- Install: `npm ci` (or `npm install`)
|
||||
- Dev: `npm run dev`
|
||||
- Build/serve: `npm run build` / `npm run start`
|
||||
- Lint: `npm run lint` / `npm run lint:fix`
|
||||
- Typecheck: `npm run typecheck`
|
||||
- Unit: `npm run test:unit` / `npm run test:coverage`
|
||||
- Function coverage: `npm run test:check-functions`
|
||||
- Coverage report: `npm run test:coverage:report`
|
||||
- E2E: `npm run test:e2e`
|
||||
- Prisma (schema in `prisma/schema.prisma`, config in `frontends/nextjs/prisma.config.ts`):
|
||||
- First-time setup: copy `.env.example` to `.env` (or ensure `DATABASE_URL` is set)
|
||||
- Commands: `npm run db:generate` / `npm run db:push` / `npm run db:migrate`
|
||||
- Validate: `npx prisma validate`
|
||||
- Coverage output: `frontends/nextjs/coverage/`
|
||||
|
||||
DBAL workflows live in `dbal/development/` (`npm run build`, `npm run test:unit`).
|
||||
|
||||
## Source + Tests
|
||||
- TypeScript + ESM. Prefer `@/…` imports inside `frontends/nextjs/src/`.
|
||||
- React components: `PascalCase.tsx`; hooks: `useThing.ts`; tests: `*.test.ts(x)`.
|
||||
- Unit tests: `frontends/nextjs/src/**/*.test.ts(x)` and `packages/*/tests/*.test.ts`; E2E: `frontends/nextjs/e2e/`.
|
||||
- Prefer one focused function (“lambda”) per file; use classes only as containers for related functions (see `.github/prompts/LAMBDA_PROMPT.md`).
|
||||
- Add/adjust tests with behavior changes; keep tests deterministic (no network, stable clocks/IDs), and parameterize where it improves coverage (`it.each()`); keep source↔test naming aligned.
|
||||
- Leave TODOs only when you’re explicitly deferring follow-up work (and include the next step).
|
||||
|
||||
## Git Hygiene
|
||||
- Commit as you go with descriptive (Conventional Commit-style) messages; default to trunk-based work on `main` unless a PR flow is required.
|
||||
- If multiple agents are working, merge/rebase carefully and avoid overwriting each other’s changes.
|
||||
- Before opening a PR, run `npm run lint`, `npm run typecheck`, and the relevant tests (from `frontends/nextjs/`).
|
||||
- PRs should include: what/why, linked issue (if any), screenshots for UI changes, and notes on DB/schema changes.
|
||||
|
||||
## Architecture Guardrails
|
||||
- Prefer data-driven config (JSON/Lua) over hard-coded TS/TSX; start with `packages/*/seed/` and `docs/architecture/data-driven-architecture.md`.
|
||||
- Prefer declarative UI via `RenderComponent` / generic renderers (see `docs/architecture/generic-page-system.md`).
|
||||
- Route data access through DBAL / the `Database` wrapper (`frontends/nextjs/src/lib/db/` or `@/lib/db`); don’t bypass it.
|
||||
- Assume multi-tenancy: include `tenantId` filtering and isolate per-tenant data.
|
||||
- UI uses Material UI (`@mui/*`) and SCSS/modules as needed; don’t introduce Radix UI or Tailwind. See `docs/RADIX_TO_MUI_MIGRATION.md` and `UI_STANDARDS.md`.
|
||||
- Package metadata: keep `packages/*/seed/metadata.json` `packageId` in `snake_case` and versions semver (e.g. `1.2.3`).
|
||||
|
||||
## CI / Workflows
|
||||
- Use `act` to reproduce and debug GitHub Actions locally (from `frontends/nextjs/`: `npm run act`, `npm run act:diagnose`; see `docs/guides/ACT_TESTING.md`).
|
||||
|
||||
If you get stuck, see `.github/prompts/EEK-STUCK.md`.
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
# Plan Feature Implementation
|
||||
|
||||
Before implementing, analyze the feature requirements:
|
||||
|
||||
1. **Check existing docs**: `docs/architecture/` for design patterns
|
||||
2. **Identify affected areas**:
|
||||
- Database schema changes? → `prisma/schema.prisma`
|
||||
- New API/DBAL operations? → `dbal/shared/api/schema/`
|
||||
- UI components? → Use declarative `RenderComponent`
|
||||
- Business logic? → Consider Lua script in `packages/*/seed/scripts/`
|
||||
|
||||
3. **Multi-tenant impact**: Does this need `tenantId` filtering?
|
||||
|
||||
4. **Permission level**: Which of the 5 levels can access this?
|
||||
- Level 1: Public
|
||||
- Level 2: User
|
||||
- Level 3: Admin
|
||||
- Level 4: God
|
||||
- Level 5: Supergod
|
||||
|
||||
5. **Create implementation checklist** with specific files to modify.
|
||||
# Plan Feature Implementation
|
||||
|
||||
Before implementing, analyze the feature requirements:
|
||||
|
||||
1. **Check existing docs**: `docs/architecture/` for design patterns
|
||||
2. **Identify affected areas**:
|
||||
- Database schema changes? → `prisma/schema.prisma`
|
||||
- New API/DBAL operations? → `dbal/shared/api/schema/`
|
||||
- UI components? → Use declarative `RenderComponent`
|
||||
- Business logic? → Consider Lua script in `packages/*/seed/scripts/`
|
||||
|
||||
3. **Multi-tenant impact**: Does this need `tenantId` filtering?
|
||||
|
||||
4. **Permission level**: Which of the 5 levels can access this?
|
||||
- Level 1: Public
|
||||
- Level 2: User
|
||||
- Level 3: Admin
|
||||
- Level 4: God
|
||||
- Level 5: Supergod
|
||||
|
||||
5. **Create implementation checklist** with specific files to modify.
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
# Design Component Architecture
|
||||
|
||||
Design a new component or feature following MetaBuilder patterns:
|
||||
|
||||
## Questions to Answer
|
||||
1. Is this better as **declarative JSON** or **React TSX**?
|
||||
- Prefer declarative for data-driven UIs
|
||||
- Use TSX only for complex interactions
|
||||
|
||||
2. Can existing packages handle this?
|
||||
- Check `packages/*/seed/components.json`
|
||||
|
||||
3. What's the data flow?
|
||||
- Database → `Database` class → Component
|
||||
- Never bypass the Database wrapper
|
||||
|
||||
## Output a Design With
|
||||
- Component tree structure
|
||||
- Props interface
|
||||
- Data dependencies
|
||||
- Permission requirements
|
||||
- Package location (new or existing)
|
||||
|
||||
## Size Constraints
|
||||
- Components: < 150 LOC
|
||||
- Split large components using composition
|
||||
# Design Component Architecture
|
||||
|
||||
Design a new component or feature following MetaBuilder patterns:
|
||||
|
||||
## Questions to Answer
|
||||
1. Is this better as **declarative JSON** or **React TSX**?
|
||||
- Prefer declarative for data-driven UIs
|
||||
- Use TSX only for complex interactions
|
||||
|
||||
2. Can existing packages handle this?
|
||||
- Check `packages/*/seed/components.json`
|
||||
|
||||
3. What's the data flow?
|
||||
- Database → `Database` class → Component
|
||||
- Never bypass the Database wrapper
|
||||
|
||||
## Output a Design With
|
||||
- Component tree structure
|
||||
- Props interface
|
||||
- Data dependencies
|
||||
- Permission requirements
|
||||
- Package location (new or existing)
|
||||
|
||||
## Size Constraints
|
||||
- Components: < 150 LOC
|
||||
- Split large components using composition
|
||||
|
||||
70
.github/prompts/workflow/5-review-code.prompt.md
vendored
70
.github/prompts/workflow/5-review-code.prompt.md
vendored
@@ -1,35 +1,35 @@
|
||||
# Code Review Checklist
|
||||
|
||||
Review code against MetaBuilder standards:
|
||||
|
||||
Run checks from `frontends/nextjs/`.
|
||||
|
||||
## Architecture
|
||||
- [ ] No raw Prisma calls - uses `Database` class
|
||||
- [ ] tenantId filter on all data queries
|
||||
- [ ] Permission level enforced appropriately
|
||||
- [ ] DBAL changes follow YAML-first pattern
|
||||
|
||||
## Components
|
||||
- [ ] Under 150 LOC (exception: recursive renderers)
|
||||
- [ ] Uses declarative pattern where possible
|
||||
- [ ] No hardcoded values that belong in DB
|
||||
- [ ] Uses `@/` absolute imports
|
||||
- [ ] Uses Material UI (`@mui/*`) and `sx`/SCSS modules (no Radix UI / Tailwind)
|
||||
|
||||
## Testing
|
||||
- [ ] Parameterized tests with `it.each()`
|
||||
- [ ] Test file next to source (`*.test.ts`)
|
||||
- [ ] Edge cases covered
|
||||
|
||||
## Security
|
||||
- [ ] No credentials in code
|
||||
- [ ] Input validation present
|
||||
- [ ] Lua scripts use sandbox (no os/io/require)
|
||||
|
||||
## Run Checks
|
||||
```bash
|
||||
npm run lint:fix
|
||||
npm run test:unit
|
||||
npm run act
|
||||
```
|
||||
# Code Review Checklist
|
||||
|
||||
Review code against MetaBuilder standards:
|
||||
|
||||
Run checks from `frontends/nextjs/`.
|
||||
|
||||
## Architecture
|
||||
- [ ] No raw Prisma calls - uses `Database` class
|
||||
- [ ] tenantId filter on all data queries
|
||||
- [ ] Permission level enforced appropriately
|
||||
- [ ] DBAL changes follow YAML-first pattern
|
||||
|
||||
## Components
|
||||
- [ ] Under 150 LOC (exception: recursive renderers)
|
||||
- [ ] Uses declarative pattern where possible
|
||||
- [ ] No hardcoded values that belong in DB
|
||||
- [ ] Uses `@/` absolute imports
|
||||
- [ ] Uses Material UI (`@mui/*`) and `sx`/SCSS modules (no Radix UI / Tailwind)
|
||||
|
||||
## Testing
|
||||
- [ ] Parameterized tests with `it.each()`
|
||||
- [ ] Test file next to source (`*.test.ts`)
|
||||
- [ ] Edge cases covered
|
||||
|
||||
## Security
|
||||
- [ ] No credentials in code
|
||||
- [ ] Input validation present
|
||||
- [ ] Lua scripts use sandbox (no os/io/require)
|
||||
|
||||
## Run Checks
|
||||
```bash
|
||||
npm run lint:fix
|
||||
npm run test:unit
|
||||
npm run act
|
||||
```
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
# Document Feature
|
||||
|
||||
Add documentation for a new feature:
|
||||
|
||||
## Code Documentation
|
||||
```typescript
|
||||
/**
|
||||
* Fetches users filtered by tenant
|
||||
* @param tenantId - The tenant to filter by (required for isolation)
|
||||
* @returns Array of User objects
|
||||
* @example
|
||||
* const users = await Database.getUsers({ tenantId: 'tenant_123' })
|
||||
*/
|
||||
```
|
||||
|
||||
## Architecture Docs
|
||||
Location: `docs/architecture/`
|
||||
- Explain the "why" not just "what"
|
||||
- Include diagrams for data flow
|
||||
- Document permission requirements
|
||||
|
||||
## Package Docs
|
||||
Each package needs:
|
||||
- `seed/metadata.json` - version, dependencies
|
||||
- `tests/README.md` - testing instructions
|
||||
- `static_content/examples.json` - usage examples
|
||||
|
||||
## Update Index
|
||||
Add to `docs/INDEX.md` or `docs/NAVIGATION.md`
|
||||
|
||||
## JSDoc Coverage Check (optional)
|
||||
Run from `frontends/nextjs/` (requires `tsx` via `npx`).
|
||||
```bash
|
||||
npx tsx ../../tools/check-jsdoc-coverage.ts
|
||||
```
|
||||
# Document Feature
|
||||
|
||||
Add documentation for a new feature:
|
||||
|
||||
## Code Documentation
|
||||
```typescript
|
||||
/**
|
||||
* Fetches users filtered by tenant
|
||||
* @param tenantId - The tenant to filter by (required for isolation)
|
||||
* @returns Array of User objects
|
||||
* @example
|
||||
* const users = await Database.getUsers({ tenantId: 'tenant_123' })
|
||||
*/
|
||||
```
|
||||
|
||||
## Architecture Docs
|
||||
Location: `docs/architecture/`
|
||||
- Explain the "why" not just "what"
|
||||
- Include diagrams for data flow
|
||||
- Document permission requirements
|
||||
|
||||
## Package Docs
|
||||
Each package needs:
|
||||
- `seed/metadata.json` - version, dependencies
|
||||
- `tests/README.md` - testing instructions
|
||||
- `static_content/examples.json` - usage examples
|
||||
|
||||
## Update Index
|
||||
Add to `docs/INDEX.md` or `docs/NAVIGATION.md`
|
||||
|
||||
## JSDoc Coverage Check (optional)
|
||||
Run from `frontends/nextjs/` (requires `tsx` via `npx`).
|
||||
```bash
|
||||
npx tsx ../../tools/check-jsdoc-coverage.ts
|
||||
```
|
||||
|
||||
1142
.github/workflows/README.md
vendored
1142
.github/workflows/README.md
vendored
File diff suppressed because it is too large
Load Diff
114
.github/workflows/ci/cli.yml
vendored
114
.github/workflows/ci/cli.yml
vendored
@@ -1,57 +1,57 @@
|
||||
name: CLI Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build MetaBuilder CLI
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build python3-pip libssl-dev
|
||||
|
||||
- name: Install Conan
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install conan
|
||||
|
||||
- name: Detect Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Install Conan dependencies
|
||||
run: |
|
||||
mkdir -p frontends/cli/build
|
||||
conan install frontends/cli \
|
||||
--output-folder frontends/cli/build \
|
||||
--build missing
|
||||
|
||||
- name: Configure CLI with CMake
|
||||
run: |
|
||||
cmake -S frontends/cli -B frontends/cli/build -G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE=frontends/cli/build/conan_toolchain.cmake
|
||||
|
||||
- name: Build CLI executable
|
||||
run: cmake --build frontends/cli/build
|
||||
|
||||
- name: Run help command to verify binary
|
||||
run: frontends/cli/build/bin/metabuilder-cli --help
|
||||
name: CLI Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build MetaBuilder CLI
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build python3-pip libssl-dev
|
||||
|
||||
- name: Install Conan
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install conan
|
||||
|
||||
- name: Detect Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Install Conan dependencies
|
||||
run: |
|
||||
mkdir -p frontends/cli/build
|
||||
conan install frontends/cli \
|
||||
--output-folder frontends/cli/build \
|
||||
--build missing
|
||||
|
||||
- name: Configure CLI with CMake
|
||||
run: |
|
||||
cmake -S frontends/cli -B frontends/cli/build -G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE=frontends/cli/build/conan_toolchain.cmake
|
||||
|
||||
- name: Build CLI executable
|
||||
run: cmake --build frontends/cli/build
|
||||
|
||||
- name: Run help command to verify binary
|
||||
run: frontends/cli/build/bin/metabuilder-cli --help
|
||||
|
||||
616
.github/workflows/ci/cpp-build.yml
vendored
616
.github/workflows/ci/cpp-build.yml
vendored
@@ -1,308 +1,308 @@
|
||||
name: C++ Build & Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- 'dbal/shared/tools/cpp-build-assistant.cjs'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- 'dbal/shared/tools/cpp-build-assistant.cjs'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-implementation:
|
||||
name: Check C++ Implementation Status
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
has_sources: ${{ steps.check.outputs.has_sources }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check if C++ sources exist
|
||||
id: check
|
||||
run: |
|
||||
if [ -d "dbal/production/src" ] && [ "$(find dbal/production/src -name '*.cpp' | wc -l)" -gt 0 ]; then
|
||||
echo "has_sources=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ C++ source files found"
|
||||
else
|
||||
echo "has_sources=false" >> $GITHUB_OUTPUT
|
||||
echo "⚠ C++ implementation not yet available - skipping build"
|
||||
fi
|
||||
|
||||
build-linux:
|
||||
name: Build on Linux
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
compiler:
|
||||
- { cc: gcc, cxx: g++ }
|
||||
- { cc: clang, cxx: clang++ }
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build ${{ matrix.compiler.cxx }}
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Initialize Conanfile
|
||||
run: bun run cpp:init
|
||||
|
||||
- name: Install Conan dependencies
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: bun run cpp:install
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
bun run cpp:build -- configure --debug
|
||||
else
|
||||
bun run cpp:configure
|
||||
fi
|
||||
|
||||
- name: Build C++ project
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: bun run cpp:build
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release' && matrix.compiler.cxx == 'g++'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.so
|
||||
retention-days: 7
|
||||
|
||||
build-macos:
|
||||
name: Build on macOS
|
||||
runs-on: macos-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
brew install cmake ninja conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
node dbal/shared/tools/cpp-build-assistant.cjs full --debug
|
||||
else
|
||||
bun run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-macos
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.dylib
|
||||
retention-days: 7
|
||||
|
||||
build-windows:
|
||||
name: Build on Windows
|
||||
runs-on: windows-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
choco install cmake ninja -y
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
node dbal/shared/tools/cpp-build-assistant.cjs full --debug
|
||||
else
|
||||
bun run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-windows
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon.exe
|
||||
dbal/production/build/*.dll
|
||||
retention-days: 7
|
||||
|
||||
code-quality:
|
||||
name: C++ Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build cppcheck clang-format
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Configure project
|
||||
run: bun run cpp:full
|
||||
|
||||
- name: Run cppcheck
|
||||
run: |
|
||||
cppcheck --enable=all --inconclusive --error-exitcode=1 \
|
||||
--suppress=missingIncludeSystem \
|
||||
-I dbal/production/include \
|
||||
dbal/production/src/
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check formatting
|
||||
run: |
|
||||
find dbal/production/src dbal/production/include -name '*.cpp' -o -name '*.hpp' | \
|
||||
xargs clang-format --dry-run --Werror
|
||||
continue-on-error: true
|
||||
|
||||
integration:
|
||||
name: Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-implementation, build-linux]
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Download Linux build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: dbal/production/build/
|
||||
|
||||
- name: Make daemon executable
|
||||
run: chmod +x dbal/production/build/dbal_daemon
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
# Start C++ daemon
|
||||
./dbal/production/build/dbal_daemon &
|
||||
DAEMON_PID=$!
|
||||
sleep 2
|
||||
|
||||
# Run TypeScript integration tests
|
||||
bun run test:unit
|
||||
|
||||
# Cleanup
|
||||
kill $DAEMON_PID
|
||||
continue-on-error: true
|
||||
name: C++ Build & Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- 'dbal/shared/tools/cpp-build-assistant.cjs'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- 'dbal/shared/tools/cpp-build-assistant.cjs'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-implementation:
|
||||
name: Check C++ Implementation Status
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
has_sources: ${{ steps.check.outputs.has_sources }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check if C++ sources exist
|
||||
id: check
|
||||
run: |
|
||||
if [ -d "dbal/production/src" ] && [ "$(find dbal/production/src -name '*.cpp' | wc -l)" -gt 0 ]; then
|
||||
echo "has_sources=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ C++ source files found"
|
||||
else
|
||||
echo "has_sources=false" >> $GITHUB_OUTPUT
|
||||
echo "⚠ C++ implementation not yet available - skipping build"
|
||||
fi
|
||||
|
||||
build-linux:
|
||||
name: Build on Linux
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
compiler:
|
||||
- { cc: gcc, cxx: g++ }
|
||||
- { cc: clang, cxx: clang++ }
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build ${{ matrix.compiler.cxx }}
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Initialize Conanfile
|
||||
run: bun run cpp:init
|
||||
|
||||
- name: Install Conan dependencies
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: bun run cpp:install
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
bun run cpp:build -- configure --debug
|
||||
else
|
||||
bun run cpp:configure
|
||||
fi
|
||||
|
||||
- name: Build C++ project
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: bun run cpp:build
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release' && matrix.compiler.cxx == 'g++'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.so
|
||||
retention-days: 7
|
||||
|
||||
build-macos:
|
||||
name: Build on macOS
|
||||
runs-on: macos-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
brew install cmake ninja conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
node dbal/shared/tools/cpp-build-assistant.cjs full --debug
|
||||
else
|
||||
bun run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-macos
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.dylib
|
||||
retention-days: 7
|
||||
|
||||
build-windows:
|
||||
name: Build on Windows
|
||||
runs-on: windows-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
choco install cmake ninja -y
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: bun run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
node dbal/shared/tools/cpp-build-assistant.cjs full --debug
|
||||
else
|
||||
bun run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: bun run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-windows
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon.exe
|
||||
dbal/production/build/*.dll
|
||||
retention-days: 7
|
||||
|
||||
code-quality:
|
||||
name: C++ Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build cppcheck clang-format
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Configure project
|
||||
run: bun run cpp:full
|
||||
|
||||
- name: Run cppcheck
|
||||
run: |
|
||||
cppcheck --enable=all --inconclusive --error-exitcode=1 \
|
||||
--suppress=missingIncludeSystem \
|
||||
-I dbal/production/include \
|
||||
dbal/production/src/
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check formatting
|
||||
run: |
|
||||
find dbal/production/src dbal/production/include -name '*.cpp' -o -name '*.hpp' | \
|
||||
xargs clang-format --dry-run --Werror
|
||||
continue-on-error: true
|
||||
|
||||
integration:
|
||||
name: Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-implementation, build-linux]
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Download Linux build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: dbal/production/build/
|
||||
|
||||
- name: Make daemon executable
|
||||
run: chmod +x dbal/production/build/dbal_daemon
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
# Start C++ daemon
|
||||
./dbal/production/build/dbal_daemon &
|
||||
DAEMON_PID=$!
|
||||
sleep 2
|
||||
|
||||
# Run TypeScript integration tests
|
||||
bun run test:unit
|
||||
|
||||
# Cleanup
|
||||
kill $DAEMON_PID
|
||||
continue-on-error: true
|
||||
|
||||
398
.github/workflows/ci/detect-stubs.yml
vendored
398
.github/workflows/ci/detect-stubs.yml
vendored
@@ -1,199 +1,199 @@
|
||||
name: Stub Implementation Detection
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main, master, develop ]
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1' # Weekly on Monday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
detect-stubs:
|
||||
name: Detect Stub Implementations
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: bun run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
# Pattern-based stub detection
|
||||
- name: Detect stub patterns
|
||||
id: detect-patterns
|
||||
run: bunx tsx ../../tools/detect-stub-implementations.ts > stub-patterns.json
|
||||
continue-on-error: true
|
||||
|
||||
# Implementation completeness analysis
|
||||
- name: Analyze implementation completeness
|
||||
id: analyze-completeness
|
||||
run: bunx tsx ../../tools/analyze-implementation-completeness.ts > implementation-analysis.json
|
||||
continue-on-error: true
|
||||
|
||||
# Generate detailed report
|
||||
- name: Generate stub report
|
||||
id: generate-report
|
||||
run: bunx tsx ../../tools/generate-stub-report.ts > stub-report.md
|
||||
continue-on-error: true
|
||||
|
||||
# Check for unimplemented TODOs in changed files (PR only)
|
||||
- name: Check changed files for stubs
|
||||
if: github.event_name == 'pull_request'
|
||||
id: check-changed
|
||||
run: |
|
||||
git diff origin/${{ github.base_ref }}...HEAD -- 'src/**/*.{ts,tsx}' | \
|
||||
grep -E '^\+.*(TODO|FIXME|not implemented|stub|placeholder|mock)' | \
|
||||
tee changed-stubs.txt || true
|
||||
|
||||
STUB_COUNT=$(wc -l < changed-stubs.txt)
|
||||
echo "stub_count=$STUB_COUNT" >> $GITHUB_OUTPUT
|
||||
continue-on-error: true
|
||||
|
||||
# Post PR comment with findings
|
||||
- name: Post stub detection comment
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let comment = '## 🔍 Stub Implementation Detection Report\n\n';
|
||||
|
||||
try {
|
||||
const patternData = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
const completenessData = JSON.parse(fs.readFileSync('implementation-analysis.json', 'utf8'));
|
||||
|
||||
// Summary table
|
||||
comment += '### Summary\n\n';
|
||||
comment += `**Pattern-Based Stubs**: ${patternData.totalStubsFound}\n`;
|
||||
comment += `**Low Completeness Items**: ${completenessData.bySeverity.high + completenessData.bySeverity.medium}\n`;
|
||||
comment += `**Average Completeness**: ${completenessData.averageCompleteness}%\n\n`;
|
||||
|
||||
// Severity breakdown
|
||||
if (patternData.totalStubsFound > 0) {
|
||||
comment += '### Severity Breakdown (Patterns)\n\n';
|
||||
comment += `| Severity | Count |\n`;
|
||||
comment += `|----------|-------|\n`;
|
||||
comment += `| 🔴 Critical | ${patternData.bySeverity.high} |\n`;
|
||||
comment += `| 🟠 Medium | ${patternData.bySeverity.medium} |\n`;
|
||||
comment += `| 🟡 Low | ${patternData.bySeverity.low} |\n\n`;
|
||||
}
|
||||
|
||||
// Type breakdown
|
||||
if (Object.values(patternData.byType).some(v => v > 0)) {
|
||||
comment += '### Issue Types\n\n';
|
||||
for (const [type, count] of Object.entries(patternData.byType)) {
|
||||
if (count > 0) {
|
||||
comment += `- **${type}**: ${count}\n`;
|
||||
}
|
||||
}
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
// Critical issues
|
||||
if (patternData.criticalIssues && patternData.criticalIssues.length > 0) {
|
||||
comment += '### 🔴 Critical Issues Found\n\n';
|
||||
comment += '<details><summary>Click to expand</summary>\n\n';
|
||||
comment += `| File | Line | Function | Type |\n`;
|
||||
comment += `|------|------|----------|------|\n`;
|
||||
patternData.criticalIssues.slice(0, 10).forEach(issue => {
|
||||
comment += `| ${issue.file} | ${issue.line} | \`${issue.function}\` | ${issue.type} |\n`;
|
||||
});
|
||||
comment += '\n</details>\n\n';
|
||||
}
|
||||
|
||||
// Recommendations
|
||||
comment += '### 📋 Recommendations\n\n';
|
||||
comment += '- [ ] Review all critical stubs before merging\n';
|
||||
comment += '- [ ] Replace TODO comments with GitHub issues\n';
|
||||
comment += '- [ ] Implement placeholder functions before production\n';
|
||||
comment += '- [ ] Run `bun run test:check-functions` to ensure coverage\n';
|
||||
comment += '- [ ] Use type system to force implementation (avoid `any` types)\n\n';
|
||||
|
||||
// Artifacts info
|
||||
comment += '### 📁 Detailed Reports\n\n';
|
||||
comment += 'Full analysis available in artifacts:\n';
|
||||
comment += '- `stub-patterns.json` - Pattern-based detection results\n';
|
||||
comment += '- `implementation-analysis.json` - Completeness scoring\n';
|
||||
comment += '- `stub-report.md` - Detailed markdown report\n';
|
||||
} catch (e) {
|
||||
comment += '⚠️ Could not generate detailed report. Check logs for errors.\n';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
# Upload detailed reports
|
||||
- name: Upload stub detection reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: stub-detection-reports
|
||||
path: |
|
||||
stub-patterns.json
|
||||
implementation-analysis.json
|
||||
stub-report.md
|
||||
changed-stubs.txt
|
||||
retention-days: 30
|
||||
|
||||
# Create check run with summary
|
||||
- name: Create check run
|
||||
uses: actions/github-script@v7
|
||||
if: always()
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let summary = '';
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
summary = `Found ${data.totalStubsFound} stub implementations (${data.bySeverity.high} high severity)`;
|
||||
} catch (e) {
|
||||
summary = 'Stub detection completed. See artifacts for details.';
|
||||
}
|
||||
|
||||
github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'Stub Implementation Detection',
|
||||
head_sha: context.sha,
|
||||
status: 'completed',
|
||||
conclusion: 'neutral',
|
||||
summary: summary
|
||||
});
|
||||
name: Stub Implementation Detection
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main, master, develop ]
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1' # Weekly on Monday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
detect-stubs:
|
||||
name: Detect Stub Implementations
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: bun run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
# Pattern-based stub detection
|
||||
- name: Detect stub patterns
|
||||
id: detect-patterns
|
||||
run: bunx tsx ../../tools/detect-stub-implementations.ts > stub-patterns.json
|
||||
continue-on-error: true
|
||||
|
||||
# Implementation completeness analysis
|
||||
- name: Analyze implementation completeness
|
||||
id: analyze-completeness
|
||||
run: bunx tsx ../../tools/analyze-implementation-completeness.ts > implementation-analysis.json
|
||||
continue-on-error: true
|
||||
|
||||
# Generate detailed report
|
||||
- name: Generate stub report
|
||||
id: generate-report
|
||||
run: bunx tsx ../../tools/generate-stub-report.ts > stub-report.md
|
||||
continue-on-error: true
|
||||
|
||||
# Check for unimplemented TODOs in changed files (PR only)
|
||||
- name: Check changed files for stubs
|
||||
if: github.event_name == 'pull_request'
|
||||
id: check-changed
|
||||
run: |
|
||||
git diff origin/${{ github.base_ref }}...HEAD -- 'src/**/*.{ts,tsx}' | \
|
||||
grep -E '^\+.*(TODO|FIXME|not implemented|stub|placeholder|mock)' | \
|
||||
tee changed-stubs.txt || true
|
||||
|
||||
STUB_COUNT=$(wc -l < changed-stubs.txt)
|
||||
echo "stub_count=$STUB_COUNT" >> $GITHUB_OUTPUT
|
||||
continue-on-error: true
|
||||
|
||||
# Post PR comment with findings
|
||||
- name: Post stub detection comment
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let comment = '## 🔍 Stub Implementation Detection Report\n\n';
|
||||
|
||||
try {
|
||||
const patternData = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
const completenessData = JSON.parse(fs.readFileSync('implementation-analysis.json', 'utf8'));
|
||||
|
||||
// Summary table
|
||||
comment += '### Summary\n\n';
|
||||
comment += `**Pattern-Based Stubs**: ${patternData.totalStubsFound}\n`;
|
||||
comment += `**Low Completeness Items**: ${completenessData.bySeverity.high + completenessData.bySeverity.medium}\n`;
|
||||
comment += `**Average Completeness**: ${completenessData.averageCompleteness}%\n\n`;
|
||||
|
||||
// Severity breakdown
|
||||
if (patternData.totalStubsFound > 0) {
|
||||
comment += '### Severity Breakdown (Patterns)\n\n';
|
||||
comment += `| Severity | Count |\n`;
|
||||
comment += `|----------|-------|\n`;
|
||||
comment += `| 🔴 Critical | ${patternData.bySeverity.high} |\n`;
|
||||
comment += `| 🟠 Medium | ${patternData.bySeverity.medium} |\n`;
|
||||
comment += `| 🟡 Low | ${patternData.bySeverity.low} |\n\n`;
|
||||
}
|
||||
|
||||
// Type breakdown
|
||||
if (Object.values(patternData.byType).some(v => v > 0)) {
|
||||
comment += '### Issue Types\n\n';
|
||||
for (const [type, count] of Object.entries(patternData.byType)) {
|
||||
if (count > 0) {
|
||||
comment += `- **${type}**: ${count}\n`;
|
||||
}
|
||||
}
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
// Critical issues
|
||||
if (patternData.criticalIssues && patternData.criticalIssues.length > 0) {
|
||||
comment += '### 🔴 Critical Issues Found\n\n';
|
||||
comment += '<details><summary>Click to expand</summary>\n\n';
|
||||
comment += `| File | Line | Function | Type |\n`;
|
||||
comment += `|------|------|----------|------|\n`;
|
||||
patternData.criticalIssues.slice(0, 10).forEach(issue => {
|
||||
comment += `| ${issue.file} | ${issue.line} | \`${issue.function}\` | ${issue.type} |\n`;
|
||||
});
|
||||
comment += '\n</details>\n\n';
|
||||
}
|
||||
|
||||
// Recommendations
|
||||
comment += '### 📋 Recommendations\n\n';
|
||||
comment += '- [ ] Review all critical stubs before merging\n';
|
||||
comment += '- [ ] Replace TODO comments with GitHub issues\n';
|
||||
comment += '- [ ] Implement placeholder functions before production\n';
|
||||
comment += '- [ ] Run `bun run test:check-functions` to ensure coverage\n';
|
||||
comment += '- [ ] Use type system to force implementation (avoid `any` types)\n\n';
|
||||
|
||||
// Artifacts info
|
||||
comment += '### 📁 Detailed Reports\n\n';
|
||||
comment += 'Full analysis available in artifacts:\n';
|
||||
comment += '- `stub-patterns.json` - Pattern-based detection results\n';
|
||||
comment += '- `implementation-analysis.json` - Completeness scoring\n';
|
||||
comment += '- `stub-report.md` - Detailed markdown report\n';
|
||||
} catch (e) {
|
||||
comment += '⚠️ Could not generate detailed report. Check logs for errors.\n';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
# Upload detailed reports
|
||||
- name: Upload stub detection reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: stub-detection-reports
|
||||
path: |
|
||||
stub-patterns.json
|
||||
implementation-analysis.json
|
||||
stub-report.md
|
||||
changed-stubs.txt
|
||||
retention-days: 30
|
||||
|
||||
# Create check run with summary
|
||||
- name: Create check run
|
||||
uses: actions/github-script@v7
|
||||
if: always()
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let summary = '';
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
summary = `Found ${data.totalStubsFound} stub implementations (${data.bySeverity.high} high severity)`;
|
||||
} catch (e) {
|
||||
summary = 'Stub detection completed. See artifacts for details.';
|
||||
}
|
||||
|
||||
github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'Stub Implementation Detection',
|
||||
head_sha: context.sha,
|
||||
status: 'completed',
|
||||
conclusion: 'neutral',
|
||||
summary: summary
|
||||
});
|
||||
|
||||
720
.github/workflows/development.yml
vendored
720
.github/workflows/development.yml
vendored
@@ -1,360 +1,360 @@
|
||||
name: Development Assistance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
code-quality-feedback:
|
||||
name: Continuous Quality Feedback
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze code metrics (no redundant checks)
|
||||
id: quality
|
||||
run: |
|
||||
# Note: Lint/build/tests are handled by gated-ci.yml
|
||||
# This job only collects metrics for architectural feedback
|
||||
|
||||
# Count TypeScript files and their sizes
|
||||
TOTAL_TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l)
|
||||
LARGE_FILES=$(find src -name "*.ts" -o -name "*.tsx" -exec wc -l {} \; 2>/dev/null | awk '$1 > 150 {print $2}' | wc -l)
|
||||
|
||||
echo "total_ts_files=$TOTAL_TS_FILES" >> $GITHUB_OUTPUT
|
||||
echo "large_files=$LARGE_FILES" >> $GITHUB_OUTPUT
|
||||
|
||||
# Check for declarative vs imperative balance
|
||||
JSON_FILES=$(find src packages -name "*.json" 2>/dev/null | wc -l)
|
||||
LUA_SCRIPTS=$(find src packages -name "*.lua" 2>/dev/null | wc -l)
|
||||
|
||||
echo "json_files=$JSON_FILES" >> $GITHUB_OUTPUT
|
||||
echo "lua_scripts=$LUA_SCRIPTS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check architectural compliance
|
||||
id: architecture
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let issues = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Get changed files
|
||||
let changedFiles = [];
|
||||
if (context.eventName === 'pull_request') {
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
changedFiles = files.map(f => f.filename);
|
||||
}
|
||||
|
||||
// Check for hardcoded components outside ui/
|
||||
const hardcodedComponents = changedFiles.filter(f =>
|
||||
f.endsWith('.tsx') &&
|
||||
f.includes('src/components/') &&
|
||||
!f.includes('src/components/ui/') &&
|
||||
!f.includes('src/components/shared/') &&
|
||||
!['RenderComponent', 'FieldRenderer', 'GenericPage'].some(g => f.includes(g))
|
||||
);
|
||||
|
||||
if (hardcodedComponents.length > 0) {
|
||||
suggestions.push(`Consider if these components could be declarative: ${hardcodedComponents.join(', ')}`);
|
||||
}
|
||||
|
||||
// Check for database changes without seed data
|
||||
const schemaChanged = changedFiles.some(f => f.includes('schema.prisma'));
|
||||
const seedChanged = changedFiles.some(f => f.includes('seed'));
|
||||
|
||||
if (schemaChanged && !seedChanged) {
|
||||
suggestions.push('Database schema changed but no seed data updates detected. Consider updating seed data.');
|
||||
}
|
||||
|
||||
// Check for new routes without PageRoutes table updates
|
||||
const routeFiles = changedFiles.filter(f => f.includes('Route') || f.includes('route'));
|
||||
if (routeFiles.length > 0) {
|
||||
suggestions.push('Route changes detected. Ensure PageRoutes table is updated for dynamic routing.');
|
||||
}
|
||||
|
||||
// Check for large TypeScript files
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
if (largeFiles > 0) {
|
||||
issues.push(`${largeFiles} TypeScript files exceed 150 lines. Consider breaking them into smaller components.`);
|
||||
}
|
||||
|
||||
return { issues, suggestions };
|
||||
|
||||
- name: Provide development feedback
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.architecture.outputs.result }}');
|
||||
const totalFiles = parseInt('${{ steps.quality.outputs.total_ts_files }}');
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
const jsonFiles = parseInt('${{ steps.quality.outputs.json_files }}');
|
||||
const luaScripts = parseInt('${{ steps.quality.outputs.lua_scripts }}');
|
||||
|
||||
let comment = `## 💻 Development Quality Feedback\n\n`;
|
||||
|
||||
comment += `### 📊 Code Metrics\n\n`;
|
||||
comment += `- TypeScript files: ${totalFiles}\n`;
|
||||
comment += `- Files >150 LOC: ${largeFiles} ${largeFiles > 0 ? '⚠️' : '✅'}\n`;
|
||||
comment += `- JSON config files: ${jsonFiles}\n`;
|
||||
comment += `- Lua scripts: ${luaScripts}\n`;
|
||||
comment += `- Declarative ratio: ${((jsonFiles + luaScripts) / Math.max(totalFiles, 1) * 100).toFixed(1)}%\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += `### ⚠️ Architectural Issues\n\n`;
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += `### 💡 Suggestions\n\n`;
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `### 🎯 Project Goals Reminder\n\n`;
|
||||
comment += `- **Declarative First:** Prefer JSON + Lua over TypeScript\n`;
|
||||
comment += `- **Component Size:** Keep files under 150 LOC\n`;
|
||||
comment += `- **Generic Renderers:** Use RenderComponent for dynamic components\n`;
|
||||
comment += `- **Database-Driven:** Store configuration in database, not code\n`;
|
||||
comment += `- **Package-Based:** Organize features as importable packages\n\n`;
|
||||
|
||||
comment += `**@copilot** can help refactor code to better align with these principles.\n\n`;
|
||||
comment += `📖 See [Architecture Guidelines](/.github/copilot-instructions.md)`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Development Quality Feedback')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
copilot-interaction:
|
||||
name: Handle Copilot Mentions
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'issue_comment' &&
|
||||
contains(github.event.comment.body, '@copilot')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Parse Copilot request
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = context.payload.comment.body.toLowerCase();
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let response = `## 🤖 Copilot Assistance\n\n`;
|
||||
|
||||
// Determine what the user is asking for
|
||||
if (comment.includes('implement') || comment.includes('fix this')) {
|
||||
response += `To implement this with Copilot assistance:\n\n`;
|
||||
response += `1. **Create a branch:** \`git checkout -b feature/issue-${issue.number}\`\n`;
|
||||
response += `2. **Use Copilot in your IDE** to generate code with context from:\n`;
|
||||
response += ` - [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += ` - [PRD.md](/PRD.md)\n`;
|
||||
response += ` - Existing package structure in \`/packages/\`\n`;
|
||||
response += `3. **Follow the architectural principles:**\n`;
|
||||
response += ` - Declarative over imperative\n`;
|
||||
response += ` - Database-driven configuration\n`;
|
||||
response += ` - Generic renderers vs hardcoded components\n`;
|
||||
response += `4. **Test your changes:** \`bun run lint && bun run test:e2e\`\n`;
|
||||
response += `5. **Create a PR** - The automated workflows will review it\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('review') || comment.includes('check')) {
|
||||
response += `Copilot can review this through:\n\n`;
|
||||
response += `- **Automated Code Review** workflow (runs on PRs)\n`;
|
||||
response += `- **Development Assistance** workflow (runs on pushes)\n`;
|
||||
response += `- **Planning & Design** workflow (runs on feature requests)\n\n`;
|
||||
response += `Create a PR to trigger comprehensive review!\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('architecture') || comment.includes('design')) {
|
||||
response += `### 🏗️ Architectural Guidance\n\n`;
|
||||
response += `MetaBuilder follows these principles:\n\n`;
|
||||
response += `1. **5-Level Architecture:** User → Admin → God → SuperGod levels\n`;
|
||||
response += `2. **Multi-Tenant:** Isolated tenant instances with independent configs\n`;
|
||||
response += `3. **Declarative Components:** JSON config + Lua scripts, not TSX\n`;
|
||||
response += `4. **Package System:** Self-contained, importable feature bundles\n`;
|
||||
response += `5. **Database-First:** All config in Prisma, not hardcoded\n\n`;
|
||||
response += `📖 Full details: [PRD.md](/PRD.md)\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('test') || comment.includes('e2e')) {
|
||||
response += `### 🧪 Testing with Copilot\n\n`;
|
||||
response += `\`\`\`bash\n`;
|
||||
response += `# Run E2E tests\n`;
|
||||
response += `bun run test:e2e\n\n`;
|
||||
response += `# Run with UI\n`;
|
||||
response += `bun run test:e2e:ui\n\n`;
|
||||
response += `# Run linter\n`;
|
||||
response += `bun run lint\n`;
|
||||
response += `\`\`\`\n\n`;
|
||||
response += `Use Copilot in your IDE to:\n`;
|
||||
response += `- Generate test cases based on user stories\n`;
|
||||
response += `- Write Playwright selectors and assertions\n`;
|
||||
response += `- Create mock data for tests\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('help') || (!comment.includes('implement') && !comment.includes('review') && !comment.includes('architecture') && !comment.includes('test'))) {
|
||||
response += `### 🆘 How to Use Copilot\n\n`;
|
||||
response += `Mention **@copilot** in comments with:\n\n`;
|
||||
response += `- \`@copilot implement this\` - Get implementation guidance\n`;
|
||||
response += `- \`@copilot review this\` - Request code review\n`;
|
||||
response += `- \`@copilot architecture\` - Get architectural guidance\n`;
|
||||
response += `- \`@copilot test this\` - Get testing guidance\n`;
|
||||
response += `- \`@copilot fix this issue\` - Request automated fix\n\n`;
|
||||
response += `**In your IDE:**\n`;
|
||||
response += `- Use GitHub Copilot with context from [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += `- Reference the [PRD](/PRD.md) when prompting\n`;
|
||||
response += `- Follow patterns from existing packages in \`/packages/\`\n\n`;
|
||||
}
|
||||
|
||||
response += `---\n`;
|
||||
response += `*This is an automated response. For detailed Copilot assistance, use the extension in your IDE with project context.*`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: response
|
||||
});
|
||||
|
||||
suggest-refactoring:
|
||||
name: Suggest Refactoring Opportunities
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze refactoring opportunities
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let opportunities = [];
|
||||
|
||||
// Look for opportunities in changed files
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
|
||||
// Check for repeated code patterns
|
||||
if (patch.split('\n').length > 100) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Size',
|
||||
suggestion: 'Large changeset - consider breaking into smaller PRs or extracting common utilities'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for hardcoded values
|
||||
if (patch.match(/['"][A-Z_]{3,}['"]\s*:/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Configuration',
|
||||
suggestion: 'Hardcoded constants detected - consider moving to database configuration'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for new TSX components
|
||||
if (file.filename.includes('components/') && file.filename.endsWith('.tsx') && file.status === 'added') {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Architecture',
|
||||
suggestion: 'New component added - could this be implemented declaratively with JSON + Lua?'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for inline styles or complex class strings
|
||||
if (patch.includes('style={{') || patch.match(/className="[^"]{50,}"/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Styling',
|
||||
suggestion: 'Complex styling detected - consider extracting to theme configuration'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (opportunities.length > 0) {
|
||||
let comment = `## 🔄 Refactoring Opportunities\n\n`;
|
||||
comment += `**@copilot** identified potential improvements:\n\n`;
|
||||
|
||||
const grouped = {};
|
||||
opportunities.forEach(opp => {
|
||||
if (!grouped[opp.type]) grouped[opp.type] = [];
|
||||
grouped[opp.type].push(opp);
|
||||
});
|
||||
|
||||
for (const [type, opps] of Object.entries(grouped)) {
|
||||
comment += `### ${type}\n\n`;
|
||||
opps.forEach(opp => {
|
||||
comment += `- **${opp.file}**: ${opp.suggestion}\n`;
|
||||
});
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `These are suggestions, not requirements. Consider them as part of continuous improvement.\n\n`;
|
||||
comment += `Use **@copilot** in your IDE to help implement these refactorings.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
name: Development Assistance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
code-quality-feedback:
|
||||
name: Continuous Quality Feedback
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze code metrics (no redundant checks)
|
||||
id: quality
|
||||
run: |
|
||||
# Note: Lint/build/tests are handled by gated-ci.yml
|
||||
# This job only collects metrics for architectural feedback
|
||||
|
||||
# Count TypeScript files and their sizes
|
||||
TOTAL_TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l)
|
||||
LARGE_FILES=$(find src -name "*.ts" -o -name "*.tsx" -exec wc -l {} \; 2>/dev/null | awk '$1 > 150 {print $2}' | wc -l)
|
||||
|
||||
echo "total_ts_files=$TOTAL_TS_FILES" >> $GITHUB_OUTPUT
|
||||
echo "large_files=$LARGE_FILES" >> $GITHUB_OUTPUT
|
||||
|
||||
# Check for declarative vs imperative balance
|
||||
JSON_FILES=$(find src packages -name "*.json" 2>/dev/null | wc -l)
|
||||
LUA_SCRIPTS=$(find src packages -name "*.lua" 2>/dev/null | wc -l)
|
||||
|
||||
echo "json_files=$JSON_FILES" >> $GITHUB_OUTPUT
|
||||
echo "lua_scripts=$LUA_SCRIPTS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check architectural compliance
|
||||
id: architecture
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let issues = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Get changed files
|
||||
let changedFiles = [];
|
||||
if (context.eventName === 'pull_request') {
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
changedFiles = files.map(f => f.filename);
|
||||
}
|
||||
|
||||
// Check for hardcoded components outside ui/
|
||||
const hardcodedComponents = changedFiles.filter(f =>
|
||||
f.endsWith('.tsx') &&
|
||||
f.includes('src/components/') &&
|
||||
!f.includes('src/components/ui/') &&
|
||||
!f.includes('src/components/shared/') &&
|
||||
!['RenderComponent', 'FieldRenderer', 'GenericPage'].some(g => f.includes(g))
|
||||
);
|
||||
|
||||
if (hardcodedComponents.length > 0) {
|
||||
suggestions.push(`Consider if these components could be declarative: ${hardcodedComponents.join(', ')}`);
|
||||
}
|
||||
|
||||
// Check for database changes without seed data
|
||||
const schemaChanged = changedFiles.some(f => f.includes('schema.prisma'));
|
||||
const seedChanged = changedFiles.some(f => f.includes('seed'));
|
||||
|
||||
if (schemaChanged && !seedChanged) {
|
||||
suggestions.push('Database schema changed but no seed data updates detected. Consider updating seed data.');
|
||||
}
|
||||
|
||||
// Check for new routes without PageRoutes table updates
|
||||
const routeFiles = changedFiles.filter(f => f.includes('Route') || f.includes('route'));
|
||||
if (routeFiles.length > 0) {
|
||||
suggestions.push('Route changes detected. Ensure PageRoutes table is updated for dynamic routing.');
|
||||
}
|
||||
|
||||
// Check for large TypeScript files
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
if (largeFiles > 0) {
|
||||
issues.push(`${largeFiles} TypeScript files exceed 150 lines. Consider breaking them into smaller components.`);
|
||||
}
|
||||
|
||||
return { issues, suggestions };
|
||||
|
||||
- name: Provide development feedback
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.architecture.outputs.result }}');
|
||||
const totalFiles = parseInt('${{ steps.quality.outputs.total_ts_files }}');
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
const jsonFiles = parseInt('${{ steps.quality.outputs.json_files }}');
|
||||
const luaScripts = parseInt('${{ steps.quality.outputs.lua_scripts }}');
|
||||
|
||||
let comment = `## 💻 Development Quality Feedback\n\n`;
|
||||
|
||||
comment += `### 📊 Code Metrics\n\n`;
|
||||
comment += `- TypeScript files: ${totalFiles}\n`;
|
||||
comment += `- Files >150 LOC: ${largeFiles} ${largeFiles > 0 ? '⚠️' : '✅'}\n`;
|
||||
comment += `- JSON config files: ${jsonFiles}\n`;
|
||||
comment += `- Lua scripts: ${luaScripts}\n`;
|
||||
comment += `- Declarative ratio: ${((jsonFiles + luaScripts) / Math.max(totalFiles, 1) * 100).toFixed(1)}%\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += `### ⚠️ Architectural Issues\n\n`;
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += `### 💡 Suggestions\n\n`;
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `### 🎯 Project Goals Reminder\n\n`;
|
||||
comment += `- **Declarative First:** Prefer JSON + Lua over TypeScript\n`;
|
||||
comment += `- **Component Size:** Keep files under 150 LOC\n`;
|
||||
comment += `- **Generic Renderers:** Use RenderComponent for dynamic components\n`;
|
||||
comment += `- **Database-Driven:** Store configuration in database, not code\n`;
|
||||
comment += `- **Package-Based:** Organize features as importable packages\n\n`;
|
||||
|
||||
comment += `**@copilot** can help refactor code to better align with these principles.\n\n`;
|
||||
comment += `📖 See [Architecture Guidelines](/.github/copilot-instructions.md)`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Development Quality Feedback')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
copilot-interaction:
|
||||
name: Handle Copilot Mentions
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'issue_comment' &&
|
||||
contains(github.event.comment.body, '@copilot')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Parse Copilot request
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = context.payload.comment.body.toLowerCase();
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let response = `## 🤖 Copilot Assistance\n\n`;
|
||||
|
||||
// Determine what the user is asking for
|
||||
if (comment.includes('implement') || comment.includes('fix this')) {
|
||||
response += `To implement this with Copilot assistance:\n\n`;
|
||||
response += `1. **Create a branch:** \`git checkout -b feature/issue-${issue.number}\`\n`;
|
||||
response += `2. **Use Copilot in your IDE** to generate code with context from:\n`;
|
||||
response += ` - [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += ` - [PRD.md](/PRD.md)\n`;
|
||||
response += ` - Existing package structure in \`/packages/\`\n`;
|
||||
response += `3. **Follow the architectural principles:**\n`;
|
||||
response += ` - Declarative over imperative\n`;
|
||||
response += ` - Database-driven configuration\n`;
|
||||
response += ` - Generic renderers vs hardcoded components\n`;
|
||||
response += `4. **Test your changes:** \`bun run lint && bun run test:e2e\`\n`;
|
||||
response += `5. **Create a PR** - The automated workflows will review it\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('review') || comment.includes('check')) {
|
||||
response += `Copilot can review this through:\n\n`;
|
||||
response += `- **Automated Code Review** workflow (runs on PRs)\n`;
|
||||
response += `- **Development Assistance** workflow (runs on pushes)\n`;
|
||||
response += `- **Planning & Design** workflow (runs on feature requests)\n\n`;
|
||||
response += `Create a PR to trigger comprehensive review!\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('architecture') || comment.includes('design')) {
|
||||
response += `### 🏗️ Architectural Guidance\n\n`;
|
||||
response += `MetaBuilder follows these principles:\n\n`;
|
||||
response += `1. **5-Level Architecture:** User → Admin → God → SuperGod levels\n`;
|
||||
response += `2. **Multi-Tenant:** Isolated tenant instances with independent configs\n`;
|
||||
response += `3. **Declarative Components:** JSON config + Lua scripts, not TSX\n`;
|
||||
response += `4. **Package System:** Self-contained, importable feature bundles\n`;
|
||||
response += `5. **Database-First:** All config in Prisma, not hardcoded\n\n`;
|
||||
response += `📖 Full details: [PRD.md](/PRD.md)\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('test') || comment.includes('e2e')) {
|
||||
response += `### 🧪 Testing with Copilot\n\n`;
|
||||
response += `\`\`\`bash\n`;
|
||||
response += `# Run E2E tests\n`;
|
||||
response += `bun run test:e2e\n\n`;
|
||||
response += `# Run with UI\n`;
|
||||
response += `bun run test:e2e:ui\n\n`;
|
||||
response += `# Run linter\n`;
|
||||
response += `bun run lint\n`;
|
||||
response += `\`\`\`\n\n`;
|
||||
response += `Use Copilot in your IDE to:\n`;
|
||||
response += `- Generate test cases based on user stories\n`;
|
||||
response += `- Write Playwright selectors and assertions\n`;
|
||||
response += `- Create mock data for tests\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('help') || (!comment.includes('implement') && !comment.includes('review') && !comment.includes('architecture') && !comment.includes('test'))) {
|
||||
response += `### 🆘 How to Use Copilot\n\n`;
|
||||
response += `Mention **@copilot** in comments with:\n\n`;
|
||||
response += `- \`@copilot implement this\` - Get implementation guidance\n`;
|
||||
response += `- \`@copilot review this\` - Request code review\n`;
|
||||
response += `- \`@copilot architecture\` - Get architectural guidance\n`;
|
||||
response += `- \`@copilot test this\` - Get testing guidance\n`;
|
||||
response += `- \`@copilot fix this issue\` - Request automated fix\n\n`;
|
||||
response += `**In your IDE:**\n`;
|
||||
response += `- Use GitHub Copilot with context from [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += `- Reference the [PRD](/PRD.md) when prompting\n`;
|
||||
response += `- Follow patterns from existing packages in \`/packages/\`\n\n`;
|
||||
}
|
||||
|
||||
response += `---\n`;
|
||||
response += `*This is an automated response. For detailed Copilot assistance, use the extension in your IDE with project context.*`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: response
|
||||
});
|
||||
|
||||
suggest-refactoring:
|
||||
name: Suggest Refactoring Opportunities
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze refactoring opportunities
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let opportunities = [];
|
||||
|
||||
// Look for opportunities in changed files
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
|
||||
// Check for repeated code patterns
|
||||
if (patch.split('\n').length > 100) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Size',
|
||||
suggestion: 'Large changeset - consider breaking into smaller PRs or extracting common utilities'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for hardcoded values
|
||||
if (patch.match(/['"][A-Z_]{3,}['"]\s*:/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Configuration',
|
||||
suggestion: 'Hardcoded constants detected - consider moving to database configuration'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for new TSX components
|
||||
if (file.filename.includes('components/') && file.filename.endsWith('.tsx') && file.status === 'added') {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Architecture',
|
||||
suggestion: 'New component added - could this be implemented declaratively with JSON + Lua?'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for inline styles or complex class strings
|
||||
if (patch.includes('style={{') || patch.match(/className="[^"]{50,}"/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Styling',
|
||||
suggestion: 'Complex styling detected - consider extracting to theme configuration'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (opportunities.length > 0) {
|
||||
let comment = `## 🔄 Refactoring Opportunities\n\n`;
|
||||
comment += `**@copilot** identified potential improvements:\n\n`;
|
||||
|
||||
const grouped = {};
|
||||
opportunities.forEach(opp => {
|
||||
if (!grouped[opp.type]) grouped[opp.type] = [];
|
||||
grouped[opp.type].push(opp);
|
||||
});
|
||||
|
||||
for (const [type, opps] of Object.entries(grouped)) {
|
||||
comment += `### ${type}\n\n`;
|
||||
opps.forEach(opp => {
|
||||
comment += `- **${opp.file}**: ${opp.suggestion}\n`;
|
||||
});
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `These are suggestions, not requirements. Consider them as part of continuous improvement.\n\n`;
|
||||
comment += `Use **@copilot** in your IDE to help implement these refactorings.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
2066
.github/workflows/gated-ci-atomic.yml
vendored
2066
.github/workflows/gated-ci-atomic.yml
vendored
File diff suppressed because it is too large
Load Diff
1220
.github/workflows/gated-ci.yml
vendored
1220
.github/workflows/gated-ci.yml
vendored
File diff suppressed because it is too large
Load Diff
1234
.github/workflows/gated-deployment.yml
vendored
1234
.github/workflows/gated-deployment.yml
vendored
File diff suppressed because it is too large
Load Diff
364
.github/workflows/issue-triage.yml
vendored
364
.github/workflows/issue-triage.yml
vendored
@@ -1,182 +1,182 @@
|
||||
name: Issue Triage and Auto-Fix
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage and Label Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Analyze and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title.toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = title + ' ' + body;
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Categorize by type
|
||||
if (text.match(/bug|error|crash|broken|fail/)) {
|
||||
labels.push('bug');
|
||||
}
|
||||
if (text.match(/feature|enhancement|add|new|implement/)) {
|
||||
labels.push('enhancement');
|
||||
}
|
||||
if (text.match(/document|readme|docs|guide/)) {
|
||||
labels.push('documentation');
|
||||
}
|
||||
if (text.match(/test|testing|spec|e2e/)) {
|
||||
labels.push('testing');
|
||||
}
|
||||
if (text.match(/security|vulnerability|exploit|xss|sql/)) {
|
||||
labels.push('security');
|
||||
}
|
||||
if (text.match(/performance|slow|optimize|speed/)) {
|
||||
labels.push('performance');
|
||||
}
|
||||
|
||||
// Categorize by priority
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.push('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.push('priority: low');
|
||||
} else {
|
||||
labels.push('priority: medium');
|
||||
}
|
||||
|
||||
// Check if it's a good first issue
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.length <= 2) {
|
||||
labels.push('good first issue');
|
||||
}
|
||||
|
||||
// Check if AI can help
|
||||
if (labels.includes('bug') || labels.includes('documentation') || labels.includes('testing')) {
|
||||
labels.push('ai-fixable');
|
||||
}
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Post welcome comment
|
||||
const aiHelpText = labels.includes('ai-fixable')
|
||||
? '\n\n🤖 This issue appears to be something AI can help with! A fix may be automatically attempted.'
|
||||
: '';
|
||||
|
||||
const comment = '👋 Thank you for opening this issue!\n\n' +
|
||||
'This issue has been automatically labeled as: ' + labels.join(', ') +
|
||||
aiHelpText + '\n\n' +
|
||||
'A maintainer will review this issue soon. In the meantime, please make sure you have provided:\n' +
|
||||
'- A clear description of the issue\n' +
|
||||
'- Steps to reproduce (for bugs)\n' +
|
||||
'- Expected vs actual behavior\n' +
|
||||
'- Any relevant error messages or screenshots\n\n' +
|
||||
'Copilot may be able to help with this issue.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
attempt-auto-fix:
|
||||
name: Attempt Automated Fix
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'ai-fixable') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'auto-fix')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Analyze issue and suggest fix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const labelList = issue.labels.map(l => l.name).join(', ');
|
||||
|
||||
const comment = '🤖 **AI-Assisted Fix Attempt**\n\n' +
|
||||
'I have analyzed this issue and here are my suggestions:\n\n' +
|
||||
'**Issue Type:** ' + labelList + '\n\n' +
|
||||
'**Suggested Actions:**\n' +
|
||||
'1. Review the issue description carefully\n' +
|
||||
'2. Check for similar issues in the repository history\n' +
|
||||
'3. Consider using Copilot to help implement the fix\n\n' +
|
||||
'**To request an automated fix:**\n' +
|
||||
'- Add the auto-fix label to this issue\n' +
|
||||
'- Ensure the issue description clearly explains:\n' +
|
||||
' - What needs to be fixed\n' +
|
||||
' - Where the issue is located (file/line if known)\n' +
|
||||
' - Expected behavior\n\n' +
|
||||
'**Note:** Complex issues may require human review before implementation.\n\n' +
|
||||
'Would you like me to attempt an automated fix? If so, please confirm by commenting "Copilot fix this issue".';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
create-fix-pr:
|
||||
name: Create Fix PR
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'create-pr'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Create fix branch and PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const branchName = 'auto-fix/issue-' + issue.number;
|
||||
|
||||
const comment = '🤖 **Automated Fix PR Creation**\n\n' +
|
||||
'I have created a branch ' + branchName + ' for this fix.\n\n' +
|
||||
'**Next Steps:**\n' +
|
||||
'1. A developer or Copilot will work on the fix in this branch\n' +
|
||||
'2. A pull request will be created automatically\n' +
|
||||
'3. The PR will be linked to this issue\n\n' +
|
||||
'**Branch:** ' + branchName + '\n\n' +
|
||||
'To work on this fix:\n' +
|
||||
'git fetch origin\n' +
|
||||
'git checkout ' + branchName + '\n\n' +
|
||||
'This issue will be automatically closed when the PR is merged.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
name: Issue Triage and Auto-Fix
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage and Label Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Analyze and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title.toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = title + ' ' + body;
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Categorize by type
|
||||
if (text.match(/bug|error|crash|broken|fail/)) {
|
||||
labels.push('bug');
|
||||
}
|
||||
if (text.match(/feature|enhancement|add|new|implement/)) {
|
||||
labels.push('enhancement');
|
||||
}
|
||||
if (text.match(/document|readme|docs|guide/)) {
|
||||
labels.push('documentation');
|
||||
}
|
||||
if (text.match(/test|testing|spec|e2e/)) {
|
||||
labels.push('testing');
|
||||
}
|
||||
if (text.match(/security|vulnerability|exploit|xss|sql/)) {
|
||||
labels.push('security');
|
||||
}
|
||||
if (text.match(/performance|slow|optimize|speed/)) {
|
||||
labels.push('performance');
|
||||
}
|
||||
|
||||
// Categorize by priority
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.push('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.push('priority: low');
|
||||
} else {
|
||||
labels.push('priority: medium');
|
||||
}
|
||||
|
||||
// Check if it's a good first issue
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.length <= 2) {
|
||||
labels.push('good first issue');
|
||||
}
|
||||
|
||||
// Check if AI can help
|
||||
if (labels.includes('bug') || labels.includes('documentation') || labels.includes('testing')) {
|
||||
labels.push('ai-fixable');
|
||||
}
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Post welcome comment
|
||||
const aiHelpText = labels.includes('ai-fixable')
|
||||
? '\n\n🤖 This issue appears to be something AI can help with! A fix may be automatically attempted.'
|
||||
: '';
|
||||
|
||||
const comment = '👋 Thank you for opening this issue!\n\n' +
|
||||
'This issue has been automatically labeled as: ' + labels.join(', ') +
|
||||
aiHelpText + '\n\n' +
|
||||
'A maintainer will review this issue soon. In the meantime, please make sure you have provided:\n' +
|
||||
'- A clear description of the issue\n' +
|
||||
'- Steps to reproduce (for bugs)\n' +
|
||||
'- Expected vs actual behavior\n' +
|
||||
'- Any relevant error messages or screenshots\n\n' +
|
||||
'Copilot may be able to help with this issue.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
attempt-auto-fix:
|
||||
name: Attempt Automated Fix
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'ai-fixable') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'auto-fix')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Analyze issue and suggest fix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const labelList = issue.labels.map(l => l.name).join(', ');
|
||||
|
||||
const comment = '🤖 **AI-Assisted Fix Attempt**\n\n' +
|
||||
'I have analyzed this issue and here are my suggestions:\n\n' +
|
||||
'**Issue Type:** ' + labelList + '\n\n' +
|
||||
'**Suggested Actions:**\n' +
|
||||
'1. Review the issue description carefully\n' +
|
||||
'2. Check for similar issues in the repository history\n' +
|
||||
'3. Consider using Copilot to help implement the fix\n\n' +
|
||||
'**To request an automated fix:**\n' +
|
||||
'- Add the auto-fix label to this issue\n' +
|
||||
'- Ensure the issue description clearly explains:\n' +
|
||||
' - What needs to be fixed\n' +
|
||||
' - Where the issue is located (file/line if known)\n' +
|
||||
' - Expected behavior\n\n' +
|
||||
'**Note:** Complex issues may require human review before implementation.\n\n' +
|
||||
'Would you like me to attempt an automated fix? If so, please confirm by commenting "Copilot fix this issue".';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
create-fix-pr:
|
||||
name: Create Fix PR
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'create-pr'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Create fix branch and PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const branchName = 'auto-fix/issue-' + issue.number;
|
||||
|
||||
const comment = '🤖 **Automated Fix PR Creation**\n\n' +
|
||||
'I have created a branch ' + branchName + ' for this fix.\n\n' +
|
||||
'**Next Steps:**\n' +
|
||||
'1. A developer or Copilot will work on the fix in this branch\n' +
|
||||
'2. A pull request will be created automatically\n' +
|
||||
'3. The PR will be linked to this issue\n\n' +
|
||||
'**Branch:** ' + branchName + '\n\n' +
|
||||
'To work on this fix:\n' +
|
||||
'git fetch origin\n' +
|
||||
'git checkout ' + branchName + '\n\n' +
|
||||
'This issue will be automatically closed when the PR is merged.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
404
.github/workflows/pr/auto-merge.yml
vendored
404
.github/workflows/pr/auto-merge.yml
vendored
@@ -1,202 +1,202 @@
|
||||
name: Auto Merge
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
check_suite:
|
||||
types: [completed]
|
||||
workflow_run:
|
||||
workflows: ["CI/CD", "Enterprise Gated CI/CD Pipeline"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
name: Auto Merge PR
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
${{
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved') ||
|
||||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
|
||||
}}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PR status and merge
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// Get PR number from event
|
||||
let prNumber;
|
||||
|
||||
if (context.payload.pull_request) {
|
||||
prNumber = context.payload.pull_request.number;
|
||||
} else if (context.payload.workflow_run) {
|
||||
// Get PR from workflow run
|
||||
const { data: prs } = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`
|
||||
});
|
||||
if (prs.length === 0) {
|
||||
console.log('No open PR found for this branch');
|
||||
return;
|
||||
}
|
||||
prNumber = prs[0].number;
|
||||
} else {
|
||||
console.log('Could not determine PR number');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Checking PR #${prNumber}`);
|
||||
|
||||
// Get PR details
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
if (pr.state !== 'open') {
|
||||
console.log('PR is not open');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pr.draft) {
|
||||
console.log('PR is still in draft');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if PR is approved
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
const latestReviews = {};
|
||||
for (const review of reviews) {
|
||||
latestReviews[review.user.login] = review.state;
|
||||
}
|
||||
|
||||
const hasApproval = Object.values(latestReviews).includes('APPROVED');
|
||||
const hasRequestChanges = Object.values(latestReviews).includes('CHANGES_REQUESTED');
|
||||
|
||||
if (!hasApproval) {
|
||||
console.log('PR has not been approved yet');
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasRequestChanges) {
|
||||
console.log('PR has requested changes');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check CI status - support both old and new gated workflows
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: pr.head.sha
|
||||
});
|
||||
|
||||
// Required checks for old CI/CD workflow
|
||||
const legacyRequiredChecks = ['Lint Code', 'Build Application', 'E2E Tests'];
|
||||
|
||||
// Required gate checks for new Enterprise Gated CI/CD Pipeline
|
||||
const gatedRequiredChecks = [
|
||||
'Gate 1: Code Quality - Passed ✅',
|
||||
'Gate 2: Testing - Passed ✅',
|
||||
'Gate 3: Build & Package - Passed ✅'
|
||||
];
|
||||
|
||||
const checkStatuses = {};
|
||||
|
||||
for (const check of checks.check_runs) {
|
||||
checkStatuses[check.name] = check.conclusion;
|
||||
}
|
||||
|
||||
console.log('Check statuses:', checkStatuses);
|
||||
|
||||
// Check if using new gated workflow or old workflow
|
||||
const hasGatedChecks = gatedRequiredChecks.some(checkName =>
|
||||
checkStatuses[checkName] !== undefined
|
||||
);
|
||||
|
||||
const requiredChecks = hasGatedChecks ? gatedRequiredChecks : legacyRequiredChecks;
|
||||
console.log('Using checks:', hasGatedChecks ? 'Enterprise Gated' : 'Legacy');
|
||||
|
||||
// Wait for all required checks to pass
|
||||
const allChecksPassed = requiredChecks.every(checkName =>
|
||||
checkStatuses[checkName] === 'success' || checkStatuses[checkName] === 'skipped'
|
||||
);
|
||||
|
||||
if (!allChecksPassed) {
|
||||
console.log('Not all required checks have passed');
|
||||
|
||||
// Check if any checks failed
|
||||
const anyChecksFailed = Object.values(checkStatuses).some(status =>
|
||||
status === 'failure'
|
||||
);
|
||||
|
||||
if (anyChecksFailed) {
|
||||
console.log('Some checks failed, not merging');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Checks are still running, will retry later');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('All conditions met, merging PR');
|
||||
|
||||
// Add comment before merging
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: '✅ All checks passed and PR is approved! Auto-merging and cleaning up branch.'
|
||||
});
|
||||
|
||||
try {
|
||||
// Merge the PR
|
||||
await github.rest.pulls.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
merge_method: 'squash',
|
||||
commit_title: `${pr.title} (#${prNumber})`,
|
||||
commit_message: pr.body || ''
|
||||
});
|
||||
|
||||
console.log('PR merged successfully');
|
||||
|
||||
// Delete the branch
|
||||
try {
|
||||
await github.rest.git.deleteRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `heads/${pr.head.ref}`
|
||||
});
|
||||
console.log(`Branch ${pr.head.ref} deleted successfully`);
|
||||
} catch (deleteError) {
|
||||
console.log('Could not delete branch:', deleteError.message);
|
||||
// Don't fail the workflow if branch deletion fails
|
||||
}
|
||||
|
||||
} catch (mergeError) {
|
||||
console.error('Failed to merge PR:', mergeError.message);
|
||||
|
||||
// Post comment about merge failure
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: `❌ Auto-merge failed: ${mergeError.message}\n\nPlease merge manually.`
|
||||
});
|
||||
}
|
||||
name: Auto Merge
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
check_suite:
|
||||
types: [completed]
|
||||
workflow_run:
|
||||
workflows: ["CI/CD", "Enterprise Gated CI/CD Pipeline"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
name: Auto Merge PR
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
${{
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved') ||
|
||||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
|
||||
}}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PR status and merge
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// Get PR number from event
|
||||
let prNumber;
|
||||
|
||||
if (context.payload.pull_request) {
|
||||
prNumber = context.payload.pull_request.number;
|
||||
} else if (context.payload.workflow_run) {
|
||||
// Get PR from workflow run
|
||||
const { data: prs } = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`
|
||||
});
|
||||
if (prs.length === 0) {
|
||||
console.log('No open PR found for this branch');
|
||||
return;
|
||||
}
|
||||
prNumber = prs[0].number;
|
||||
} else {
|
||||
console.log('Could not determine PR number');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Checking PR #${prNumber}`);
|
||||
|
||||
// Get PR details
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
if (pr.state !== 'open') {
|
||||
console.log('PR is not open');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pr.draft) {
|
||||
console.log('PR is still in draft');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if PR is approved
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
const latestReviews = {};
|
||||
for (const review of reviews) {
|
||||
latestReviews[review.user.login] = review.state;
|
||||
}
|
||||
|
||||
const hasApproval = Object.values(latestReviews).includes('APPROVED');
|
||||
const hasRequestChanges = Object.values(latestReviews).includes('CHANGES_REQUESTED');
|
||||
|
||||
if (!hasApproval) {
|
||||
console.log('PR has not been approved yet');
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasRequestChanges) {
|
||||
console.log('PR has requested changes');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check CI status - support both old and new gated workflows
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: pr.head.sha
|
||||
});
|
||||
|
||||
// Required checks for old CI/CD workflow
|
||||
const legacyRequiredChecks = ['Lint Code', 'Build Application', 'E2E Tests'];
|
||||
|
||||
// Required gate checks for new Enterprise Gated CI/CD Pipeline
|
||||
const gatedRequiredChecks = [
|
||||
'Gate 1: Code Quality - Passed ✅',
|
||||
'Gate 2: Testing - Passed ✅',
|
||||
'Gate 3: Build & Package - Passed ✅'
|
||||
];
|
||||
|
||||
const checkStatuses = {};
|
||||
|
||||
for (const check of checks.check_runs) {
|
||||
checkStatuses[check.name] = check.conclusion;
|
||||
}
|
||||
|
||||
console.log('Check statuses:', checkStatuses);
|
||||
|
||||
// Check if using new gated workflow or old workflow
|
||||
const hasGatedChecks = gatedRequiredChecks.some(checkName =>
|
||||
checkStatuses[checkName] !== undefined
|
||||
);
|
||||
|
||||
const requiredChecks = hasGatedChecks ? gatedRequiredChecks : legacyRequiredChecks;
|
||||
console.log('Using checks:', hasGatedChecks ? 'Enterprise Gated' : 'Legacy');
|
||||
|
||||
// Wait for all required checks to pass
|
||||
const allChecksPassed = requiredChecks.every(checkName =>
|
||||
checkStatuses[checkName] === 'success' || checkStatuses[checkName] === 'skipped'
|
||||
);
|
||||
|
||||
if (!allChecksPassed) {
|
||||
console.log('Not all required checks have passed');
|
||||
|
||||
// Check if any checks failed
|
||||
const anyChecksFailed = Object.values(checkStatuses).some(status =>
|
||||
status === 'failure'
|
||||
);
|
||||
|
||||
if (anyChecksFailed) {
|
||||
console.log('Some checks failed, not merging');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Checks are still running, will retry later');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('All conditions met, merging PR');
|
||||
|
||||
// Add comment before merging
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: '✅ All checks passed and PR is approved! Auto-merging and cleaning up branch.'
|
||||
});
|
||||
|
||||
try {
|
||||
// Merge the PR
|
||||
await github.rest.pulls.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
merge_method: 'squash',
|
||||
commit_title: `${pr.title} (#${prNumber})`,
|
||||
commit_message: pr.body || ''
|
||||
});
|
||||
|
||||
console.log('PR merged successfully');
|
||||
|
||||
// Delete the branch
|
||||
try {
|
||||
await github.rest.git.deleteRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `heads/${pr.head.ref}`
|
||||
});
|
||||
console.log(`Branch ${pr.head.ref} deleted successfully`);
|
||||
} catch (deleteError) {
|
||||
console.log('Could not delete branch:', deleteError.message);
|
||||
// Don't fail the workflow if branch deletion fails
|
||||
}
|
||||
|
||||
} catch (mergeError) {
|
||||
console.error('Failed to merge PR:', mergeError.message);
|
||||
|
||||
// Post comment about merge failure
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: `❌ Auto-merge failed: ${mergeError.message}\n\nPlease merge manually.`
|
||||
});
|
||||
}
|
||||
|
||||
554
.github/workflows/pr/code-review.yml
vendored
554
.github/workflows/pr/code-review.yml
vendored
@@ -1,277 +1,277 @@
|
||||
name: Automated Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: read
|
||||
|
||||
jobs:
|
||||
automated-review:
|
||||
name: AI-Assisted Code Review
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: bun run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run linter for review
|
||||
id: lint
|
||||
run: |
|
||||
bun run lint > lint-output.txt 2>&1 || echo "LINT_FAILED=true" >> $GITHUB_OUTPUT
|
||||
cat lint-output.txt
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze code changes
|
||||
id: analyze
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
// Get PR diff
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let issues = [];
|
||||
let warnings = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Analyze each file
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
const filename = file.filename;
|
||||
|
||||
// Check for security issues
|
||||
if (patch.match(/eval\s*\(/)) {
|
||||
issues.push(`⚠️ **Security**: Use of \`eval()\` found in ${filename}`);
|
||||
}
|
||||
if (patch.match(/innerHTML\s*=/)) {
|
||||
warnings.push(`⚠️ **Security**: Direct \`innerHTML\` usage in ${filename}. Consider using safer alternatives.`);
|
||||
}
|
||||
if (patch.match(/dangerouslySetInnerHTML/)) {
|
||||
warnings.push(`⚠️ **Security**: \`dangerouslySetInnerHTML\` usage in ${filename}. Ensure content is sanitized.`);
|
||||
}
|
||||
|
||||
// Check for code quality
|
||||
if (patch.match(/console\.(log|debug|info)/)) {
|
||||
warnings.push(`🔍 **Code Quality**: Console statements found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/debugger/)) {
|
||||
issues.push(`🐛 **Debug Code**: Debugger statement found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/(:\s*any\b|\bany\s*[>;,\)])/)) {
|
||||
suggestions.push(`💡 **Type Safety**: Consider replacing \`any\` types with specific types in ${filename}`);
|
||||
}
|
||||
|
||||
// Check for best practices
|
||||
if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {
|
||||
if (patch.match(/useEffect.*\[\]/) && !patch.includes('// eslint-disable')) {
|
||||
suggestions.push(`💡 **React**: Empty dependency array in useEffect in ${filename}. Verify if intentional.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for large files
|
||||
if (file.additions > 500) {
|
||||
warnings.push(`📏 **File Size**: ${filename} has ${file.additions} additions. Consider breaking into smaller files.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Read lint output if exists
|
||||
let lintIssues = '';
|
||||
try {
|
||||
lintIssues = fs.readFileSync('lint-output.txt', 'utf8');
|
||||
} catch (e) {
|
||||
// File doesn't exist
|
||||
}
|
||||
|
||||
// Determine if auto-approve is appropriate
|
||||
const hasBlockingIssues = issues.length > 0 || lintIssues.includes('error');
|
||||
|
||||
return {
|
||||
issues,
|
||||
warnings,
|
||||
suggestions,
|
||||
lintIssues,
|
||||
hasBlockingIssues,
|
||||
fileCount: files.length,
|
||||
totalAdditions: files.reduce((sum, f) => sum + f.additions, 0),
|
||||
totalDeletions: files.reduce((sum, f) => sum + f.deletions, 0)
|
||||
};
|
||||
|
||||
- name: Post review comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let comment = '## 🤖 Automated Code Review\n\n';
|
||||
comment += `**Changes Summary:**\n`;
|
||||
comment += `- Files changed: ${analysis.fileCount}\n`;
|
||||
comment += `- Lines added: ${analysis.totalAdditions}\n`;
|
||||
comment += `- Lines deleted: ${analysis.totalDeletions}\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += '### ❌ Blocking Issues\n\n';
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
comment += '### ⚠️ Warnings\n\n';
|
||||
analysis.warnings.forEach(warning => comment += `- ${warning}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += '### 💡 Suggestions\n\n';
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.lintIssues && analysis.lintIssues.includes('error')) {
|
||||
comment += '### 🔴 Linting Errors\n\n';
|
||||
comment += '```\n' + analysis.lintIssues + '\n```\n\n';
|
||||
}
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
comment += '---\n';
|
||||
comment += '### ❌ Review Status: **CHANGES REQUESTED**\n\n';
|
||||
comment += 'Please address the blocking issues above before this PR can be approved.\n';
|
||||
} else {
|
||||
comment += '---\n';
|
||||
comment += '### ✅ Review Status: **APPROVED**\n\n';
|
||||
comment += 'No blocking issues found! This PR looks good to merge after CI checks pass.\n';
|
||||
}
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Automated Code Review')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add labels based on review
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let labels = [];
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
labels.push('needs-changes');
|
||||
} else {
|
||||
labels.push('ready-for-review');
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
labels.push('has-warnings');
|
||||
}
|
||||
|
||||
if (analysis.totalAdditions > 500) {
|
||||
labels.push('large-pr');
|
||||
}
|
||||
|
||||
// Remove conflicting labels first
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'needs-changes'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'ready-for-review'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
// Add new labels
|
||||
for (const label of labels) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: [label]
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`Label ${label} might not exist, skipping...`);
|
||||
}
|
||||
}
|
||||
|
||||
- name: Auto-approve if no issues
|
||||
if: steps.analyze.outputs.result && !fromJSON(steps.analyze.outputs.result).hasBlockingIssues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.pulls.createReview({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
event: 'APPROVE',
|
||||
body: '✅ Automated review passed! No blocking issues found. This PR is approved pending successful CI checks.'
|
||||
});
|
||||
name: Automated Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: read
|
||||
|
||||
jobs:
|
||||
automated-review:
|
||||
name: AI-Assisted Code Review
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: bun run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run linter for review
|
||||
id: lint
|
||||
run: |
|
||||
bun run lint > lint-output.txt 2>&1 || echo "LINT_FAILED=true" >> $GITHUB_OUTPUT
|
||||
cat lint-output.txt
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze code changes
|
||||
id: analyze
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
// Get PR diff
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let issues = [];
|
||||
let warnings = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Analyze each file
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
const filename = file.filename;
|
||||
|
||||
// Check for security issues
|
||||
if (patch.match(/eval\s*\(/)) {
|
||||
issues.push(`⚠️ **Security**: Use of \`eval()\` found in ${filename}`);
|
||||
}
|
||||
if (patch.match(/innerHTML\s*=/)) {
|
||||
warnings.push(`⚠️ **Security**: Direct \`innerHTML\` usage in ${filename}. Consider using safer alternatives.`);
|
||||
}
|
||||
if (patch.match(/dangerouslySetInnerHTML/)) {
|
||||
warnings.push(`⚠️ **Security**: \`dangerouslySetInnerHTML\` usage in ${filename}. Ensure content is sanitized.`);
|
||||
}
|
||||
|
||||
// Check for code quality
|
||||
if (patch.match(/console\.(log|debug|info)/)) {
|
||||
warnings.push(`🔍 **Code Quality**: Console statements found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/debugger/)) {
|
||||
issues.push(`🐛 **Debug Code**: Debugger statement found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/(:\s*any\b|\bany\s*[>;,\)])/)) {
|
||||
suggestions.push(`💡 **Type Safety**: Consider replacing \`any\` types with specific types in ${filename}`);
|
||||
}
|
||||
|
||||
// Check for best practices
|
||||
if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {
|
||||
if (patch.match(/useEffect.*\[\]/) && !patch.includes('// eslint-disable')) {
|
||||
suggestions.push(`💡 **React**: Empty dependency array in useEffect in ${filename}. Verify if intentional.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for large files
|
||||
if (file.additions > 500) {
|
||||
warnings.push(`📏 **File Size**: ${filename} has ${file.additions} additions. Consider breaking into smaller files.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Read lint output if exists
|
||||
let lintIssues = '';
|
||||
try {
|
||||
lintIssues = fs.readFileSync('lint-output.txt', 'utf8');
|
||||
} catch (e) {
|
||||
// File doesn't exist
|
||||
}
|
||||
|
||||
// Determine if auto-approve is appropriate
|
||||
const hasBlockingIssues = issues.length > 0 || lintIssues.includes('error');
|
||||
|
||||
return {
|
||||
issues,
|
||||
warnings,
|
||||
suggestions,
|
||||
lintIssues,
|
||||
hasBlockingIssues,
|
||||
fileCount: files.length,
|
||||
totalAdditions: files.reduce((sum, f) => sum + f.additions, 0),
|
||||
totalDeletions: files.reduce((sum, f) => sum + f.deletions, 0)
|
||||
};
|
||||
|
||||
- name: Post review comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let comment = '## 🤖 Automated Code Review\n\n';
|
||||
comment += `**Changes Summary:**\n`;
|
||||
comment += `- Files changed: ${analysis.fileCount}\n`;
|
||||
comment += `- Lines added: ${analysis.totalAdditions}\n`;
|
||||
comment += `- Lines deleted: ${analysis.totalDeletions}\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += '### ❌ Blocking Issues\n\n';
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
comment += '### ⚠️ Warnings\n\n';
|
||||
analysis.warnings.forEach(warning => comment += `- ${warning}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += '### 💡 Suggestions\n\n';
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.lintIssues && analysis.lintIssues.includes('error')) {
|
||||
comment += '### 🔴 Linting Errors\n\n';
|
||||
comment += '```\n' + analysis.lintIssues + '\n```\n\n';
|
||||
}
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
comment += '---\n';
|
||||
comment += '### ❌ Review Status: **CHANGES REQUESTED**\n\n';
|
||||
comment += 'Please address the blocking issues above before this PR can be approved.\n';
|
||||
} else {
|
||||
comment += '---\n';
|
||||
comment += '### ✅ Review Status: **APPROVED**\n\n';
|
||||
comment += 'No blocking issues found! This PR looks good to merge after CI checks pass.\n';
|
||||
}
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Automated Code Review')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add labels based on review
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let labels = [];
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
labels.push('needs-changes');
|
||||
} else {
|
||||
labels.push('ready-for-review');
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
labels.push('has-warnings');
|
||||
}
|
||||
|
||||
if (analysis.totalAdditions > 500) {
|
||||
labels.push('large-pr');
|
||||
}
|
||||
|
||||
// Remove conflicting labels first
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'needs-changes'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'ready-for-review'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
// Add new labels
|
||||
for (const label of labels) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: [label]
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`Label ${label} might not exist, skipping...`);
|
||||
}
|
||||
}
|
||||
|
||||
- name: Auto-approve if no issues
|
||||
if: steps.analyze.outputs.result && !fromJSON(steps.analyze.outputs.result).hasBlockingIssues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.pulls.createReview({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
event: 'APPROVE',
|
||||
body: '✅ Automated review passed! No blocking issues found. This PR is approved pending successful CI checks.'
|
||||
});
|
||||
|
||||
264
.github/workflows/pr/merge-conflict-check.yml
vendored
264
.github/workflows/pr/merge-conflict-check.yml
vendored
@@ -1,132 +1,132 @@
|
||||
name: Check for Merge Conflicts
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
# Also run when the base branch is updated
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
|
||||
jobs:
|
||||
check-conflicts:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref || github.event.repository.default_branch }}
|
||||
|
||||
- name: Check for merge conflicts
|
||||
id: conflict-check
|
||||
run: |
|
||||
# Determine the base branch
|
||||
BASE_BRANCH="${{ github.base_ref }}"
|
||||
if [ -z "$BASE_BRANCH" ]; then
|
||||
BASE_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
fi
|
||||
|
||||
echo "Checking for conflicts with origin/$BASE_BRANCH"
|
||||
|
||||
# Try to merge the base branch to see if there are conflicts
|
||||
if git merge-tree $(git merge-base HEAD origin/$BASE_BRANCH) origin/$BASE_BRANCH HEAD | grep -q "^<<<<<"; then
|
||||
echo "has_conflicts=true" >> $GITHUB_OUTPUT
|
||||
echo "✗ Merge conflicts detected!"
|
||||
else
|
||||
echo "has_conflicts=false" >> $GITHUB_OUTPUT
|
||||
echo "✓ No merge conflicts detected"
|
||||
fi
|
||||
|
||||
- name: Comment on PR if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = `## ⚠️ Merge Conflicts Detected
|
||||
|
||||
@copilot This pull request has merge conflicts that need to be resolved.
|
||||
|
||||
**Please resolve the conflicts by:**
|
||||
1. Merging the latest changes from the base branch
|
||||
2. Resolving any conflicting files
|
||||
3. Pushing the updated changes
|
||||
|
||||
---
|
||||
*This is an automated message from the merge conflict checker.*`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(comment =>
|
||||
comment.user.type === 'Bot' &&
|
||||
comment.body.includes('Merge Conflicts Detected')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
// Create new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add label if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['merge-conflict']
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label might not exist yet, skipping...');
|
||||
}
|
||||
|
||||
- name: Remove label if no conflicts
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'false' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'merge-conflict'
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label does not exist or is not applied, skipping...');
|
||||
}
|
||||
|
||||
- name: Fail if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true'
|
||||
run: |
|
||||
echo "❌ This PR has merge conflicts and cannot be merged."
|
||||
exit 1
|
||||
name: Check for Merge Conflicts
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
# Also run when the base branch is updated
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
|
||||
jobs:
|
||||
check-conflicts:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref || github.event.repository.default_branch }}
|
||||
|
||||
- name: Check for merge conflicts
|
||||
id: conflict-check
|
||||
run: |
|
||||
# Determine the base branch
|
||||
BASE_BRANCH="${{ github.base_ref }}"
|
||||
if [ -z "$BASE_BRANCH" ]; then
|
||||
BASE_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
fi
|
||||
|
||||
echo "Checking for conflicts with origin/$BASE_BRANCH"
|
||||
|
||||
# Try to merge the base branch to see if there are conflicts
|
||||
if git merge-tree $(git merge-base HEAD origin/$BASE_BRANCH) origin/$BASE_BRANCH HEAD | grep -q "^<<<<<"; then
|
||||
echo "has_conflicts=true" >> $GITHUB_OUTPUT
|
||||
echo "✗ Merge conflicts detected!"
|
||||
else
|
||||
echo "has_conflicts=false" >> $GITHUB_OUTPUT
|
||||
echo "✓ No merge conflicts detected"
|
||||
fi
|
||||
|
||||
- name: Comment on PR if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = `## ⚠️ Merge Conflicts Detected
|
||||
|
||||
@copilot This pull request has merge conflicts that need to be resolved.
|
||||
|
||||
**Please resolve the conflicts by:**
|
||||
1. Merging the latest changes from the base branch
|
||||
2. Resolving any conflicting files
|
||||
3. Pushing the updated changes
|
||||
|
||||
---
|
||||
*This is an automated message from the merge conflict checker.*`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(comment =>
|
||||
comment.user.type === 'Bot' &&
|
||||
comment.body.includes('Merge Conflicts Detected')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
// Create new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add label if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['merge-conflict']
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label might not exist yet, skipping...');
|
||||
}
|
||||
|
||||
- name: Remove label if no conflicts
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'false' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'merge-conflict'
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label does not exist or is not applied, skipping...');
|
||||
}
|
||||
|
||||
- name: Fail if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true'
|
||||
run: |
|
||||
echo "❌ This PR has merge conflicts and cannot be merged."
|
||||
exit 1
|
||||
|
||||
386
.github/workflows/pr/pr-management.yml
vendored
386
.github/workflows/pr/pr-management.yml
vendored
@@ -1,193 +1,193 @@
|
||||
name: PR Labeling and Management
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label-pr:
|
||||
name: Auto-Label Pull Request
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened' || github.event.action == 'synchronize'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze PR and add labels
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// Get PR files
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Analyze file changes
|
||||
const fileTypes = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
tests: files.some(f => f.filename.includes('test') || f.filename.includes('spec') || f.filename.includes('e2e')),
|
||||
docs: files.some(f => f.filename.includes('README') || f.filename.includes('.md') || f.filename.includes('docs/')),
|
||||
components: files.some(f => f.filename.includes('components/') || f.filename.includes('.tsx')),
|
||||
styles: files.some(f => f.filename.includes('.css') || f.filename.includes('style')),
|
||||
config: files.some(f => f.filename.match(/\.(json|yml|yaml|config\.(js|ts))$/)),
|
||||
dependencies: files.some(f => f.filename === 'package.json' || f.filename === 'package-lock.json'),
|
||||
};
|
||||
|
||||
if (fileTypes.workflows) labels.push('workflows');
|
||||
if (fileTypes.tests) labels.push('tests');
|
||||
if (fileTypes.docs) labels.push('documentation');
|
||||
if (fileTypes.components) labels.push('ui');
|
||||
if (fileTypes.styles) labels.push('styling');
|
||||
if (fileTypes.config) labels.push('configuration');
|
||||
if (fileTypes.dependencies) labels.push('dependencies');
|
||||
|
||||
// Size labels
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
if (totalChanges < 50) {
|
||||
labels.push('size: small');
|
||||
} else if (totalChanges < 200) {
|
||||
labels.push('size: medium');
|
||||
} else {
|
||||
labels.push('size: large');
|
||||
}
|
||||
|
||||
// Check PR title for type
|
||||
const title = pr.title.toLowerCase();
|
||||
if (title.match(/^fix|bug/)) labels.push('bug');
|
||||
if (title.match(/^feat|feature|add/)) labels.push('enhancement');
|
||||
if (title.match(/^refactor/)) labels.push('refactor');
|
||||
if (title.match(/^docs/)) labels.push('documentation');
|
||||
if (title.match(/^test/)) labels.push('tests');
|
||||
if (title.match(/^chore/)) labels.push('chore');
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
check-pr-description:
|
||||
name: Check PR Description
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Validate PR description
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
|
||||
let issues = [];
|
||||
|
||||
// Check if description is too short
|
||||
if (body.length < 50) {
|
||||
issues.push('PR description is too short. Please provide more details about the changes.');
|
||||
}
|
||||
|
||||
// Check if description links to an issue
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) {
|
||||
issues.push('Consider linking to a related issue using #issue_number');
|
||||
}
|
||||
|
||||
// Check for test information
|
||||
if (body.toLowerCase().includes('test') === false &&
|
||||
!pr.labels.some(l => l.name === 'documentation')) {
|
||||
issues.push('Please mention how these changes were tested.');
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
const issueList = issues.map(i => '- [ ] ' + i).join('\n');
|
||||
const comment = [
|
||||
'## \uD83D\uDCCB PR Description Checklist',
|
||||
'',
|
||||
'The following items could improve this PR:',
|
||||
'',
|
||||
issueList,
|
||||
'',
|
||||
'**Good PR descriptions include:**',
|
||||
'- What changes were made and why',
|
||||
'- How to test the changes',
|
||||
'- Any breaking changes or special considerations',
|
||||
'- Links to related issues',
|
||||
'- Screenshots (for UI changes)',
|
||||
'',
|
||||
'This is a friendly reminder to help maintain code quality! \uD83D\uDE0A'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
link-related-issues:
|
||||
name: Link Related Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Find and link related issues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
const title = pr.title;
|
||||
|
||||
// Extract issue numbers from PR body
|
||||
const issueNumbers = [...body.matchAll(/#(\d+)/g)].map(m => m[1]);
|
||||
|
||||
if (issueNumbers.length > 0) {
|
||||
const relatedList = issueNumbers.map(n => '#' + n).join(', ');
|
||||
const comment = [
|
||||
'\uD83D\uDD17 **Related Issues**',
|
||||
'',
|
||||
'This PR is related to: ' + relatedList,
|
||||
'',
|
||||
'These issues will be automatically closed when this PR is merged.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
// Add comment to related issues
|
||||
for (const issueNum of issueNumbers) {
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: parseInt(issueNum),
|
||||
body: '\uD83D\uDD17 Pull request #' + pr.number + ' has been created to address this issue.'
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not comment on issue #' + issueNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
name: PR Labeling and Management
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label-pr:
|
||||
name: Auto-Label Pull Request
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened' || github.event.action == 'synchronize'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze PR and add labels
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// Get PR files
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Analyze file changes
|
||||
const fileTypes = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
tests: files.some(f => f.filename.includes('test') || f.filename.includes('spec') || f.filename.includes('e2e')),
|
||||
docs: files.some(f => f.filename.includes('README') || f.filename.includes('.md') || f.filename.includes('docs/')),
|
||||
components: files.some(f => f.filename.includes('components/') || f.filename.includes('.tsx')),
|
||||
styles: files.some(f => f.filename.includes('.css') || f.filename.includes('style')),
|
||||
config: files.some(f => f.filename.match(/\.(json|yml|yaml|config\.(js|ts))$/)),
|
||||
dependencies: files.some(f => f.filename === 'package.json' || f.filename === 'package-lock.json'),
|
||||
};
|
||||
|
||||
if (fileTypes.workflows) labels.push('workflows');
|
||||
if (fileTypes.tests) labels.push('tests');
|
||||
if (fileTypes.docs) labels.push('documentation');
|
||||
if (fileTypes.components) labels.push('ui');
|
||||
if (fileTypes.styles) labels.push('styling');
|
||||
if (fileTypes.config) labels.push('configuration');
|
||||
if (fileTypes.dependencies) labels.push('dependencies');
|
||||
|
||||
// Size labels
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
if (totalChanges < 50) {
|
||||
labels.push('size: small');
|
||||
} else if (totalChanges < 200) {
|
||||
labels.push('size: medium');
|
||||
} else {
|
||||
labels.push('size: large');
|
||||
}
|
||||
|
||||
// Check PR title for type
|
||||
const title = pr.title.toLowerCase();
|
||||
if (title.match(/^fix|bug/)) labels.push('bug');
|
||||
if (title.match(/^feat|feature|add/)) labels.push('enhancement');
|
||||
if (title.match(/^refactor/)) labels.push('refactor');
|
||||
if (title.match(/^docs/)) labels.push('documentation');
|
||||
if (title.match(/^test/)) labels.push('tests');
|
||||
if (title.match(/^chore/)) labels.push('chore');
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
check-pr-description:
|
||||
name: Check PR Description
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Validate PR description
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
|
||||
let issues = [];
|
||||
|
||||
// Check if description is too short
|
||||
if (body.length < 50) {
|
||||
issues.push('PR description is too short. Please provide more details about the changes.');
|
||||
}
|
||||
|
||||
// Check if description links to an issue
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) {
|
||||
issues.push('Consider linking to a related issue using #issue_number');
|
||||
}
|
||||
|
||||
// Check for test information
|
||||
if (body.toLowerCase().includes('test') === false &&
|
||||
!pr.labels.some(l => l.name === 'documentation')) {
|
||||
issues.push('Please mention how these changes were tested.');
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
const issueList = issues.map(i => '- [ ] ' + i).join('\n');
|
||||
const comment = [
|
||||
'## \uD83D\uDCCB PR Description Checklist',
|
||||
'',
|
||||
'The following items could improve this PR:',
|
||||
'',
|
||||
issueList,
|
||||
'',
|
||||
'**Good PR descriptions include:**',
|
||||
'- What changes were made and why',
|
||||
'- How to test the changes',
|
||||
'- Any breaking changes or special considerations',
|
||||
'- Links to related issues',
|
||||
'- Screenshots (for UI changes)',
|
||||
'',
|
||||
'This is a friendly reminder to help maintain code quality! \uD83D\uDE0A'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
link-related-issues:
|
||||
name: Link Related Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Find and link related issues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
const title = pr.title;
|
||||
|
||||
// Extract issue numbers from PR body
|
||||
const issueNumbers = [...body.matchAll(/#(\d+)/g)].map(m => m[1]);
|
||||
|
||||
if (issueNumbers.length > 0) {
|
||||
const relatedList = issueNumbers.map(n => '#' + n).join(', ');
|
||||
const comment = [
|
||||
'\uD83D\uDD17 **Related Issues**',
|
||||
'',
|
||||
'This PR is related to: ' + relatedList,
|
||||
'',
|
||||
'These issues will be automatically closed when this PR is merged.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
// Add comment to related issues
|
||||
for (const issueNum of issueNumbers) {
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: parseInt(issueNum),
|
||||
body: '\uD83D\uDD17 Pull request #' + pr.number + ' has been created to address this issue.'
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not comment on issue #' + issueNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
436
.github/workflows/quality/planning.yml
vendored
436
.github/workflows/quality/planning.yml
vendored
@@ -1,218 +1,218 @@
|
||||
name: Planning & Design
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
architecture-review:
|
||||
name: Architecture & Design Review
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
(github.event.label.name == 'enhancement' || github.event.label.name == 'feature-request')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Review against architecture principles
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title;
|
||||
const body = issue.body || '';
|
||||
|
||||
let suggestions = [];
|
||||
let questions = [];
|
||||
|
||||
// Check if feature aligns with declarative approach
|
||||
if (body.toLowerCase().includes('component') && !body.toLowerCase().includes('json')) {
|
||||
suggestions.push('💡 Consider implementing this as a **declarative component** using JSON configuration and Lua scripts instead of a TypeScript file.');
|
||||
}
|
||||
|
||||
// Check if database schema is mentioned
|
||||
if (!body.toLowerCase().includes('database') && !body.toLowerCase().includes('schema')) {
|
||||
questions.push('🤔 Will this feature require database schema changes? Consider adding Prisma schema details.');
|
||||
}
|
||||
|
||||
// Check if package structure is considered
|
||||
if (body.toLowerCase().includes('new') && !body.toLowerCase().includes('package')) {
|
||||
suggestions.push('📦 This might be a good candidate for a **package-based implementation** with isolated seed data.');
|
||||
}
|
||||
|
||||
// Check for multi-tenant considerations
|
||||
if (!body.toLowerCase().includes('tenant') && !body.toLowerCase().includes('supergod')) {
|
||||
questions.push('🏢 How should this feature work across different **tenants**? Should it be tenant-specific or global?');
|
||||
}
|
||||
|
||||
// Check for permission levels
|
||||
if (!body.toLowerCase().match(/level [1-5]|user|admin|god|supergod/)) {
|
||||
questions.push('🔐 Which **permission levels** should have access to this feature? (user/admin/god/supergod)');
|
||||
}
|
||||
|
||||
// Check for Lua consideration
|
||||
if (body.toLowerCase().includes('logic') && !body.toLowerCase().includes('lua')) {
|
||||
suggestions.push('🌙 Consider implementing business logic in **Lua scripts** for better flexibility and sandboxing.');
|
||||
}
|
||||
|
||||
let comment = `## 🏗️ Architecture Review\n\n`;
|
||||
comment += `Thank you for proposing this enhancement! Here's an architectural review:\n\n`;
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
comment += `### 💡 Architectural Suggestions\n\n`;
|
||||
suggestions.forEach(s => comment += `${s}\n\n`);
|
||||
}
|
||||
|
||||
if (questions.length > 0) {
|
||||
comment += `### 🤔 Questions to Consider\n\n`;
|
||||
questions.forEach(q => comment += `${q}\n\n`);
|
||||
}
|
||||
|
||||
comment += `### ✅ Design Checklist\n\n`;
|
||||
comment += `- [ ] Database schema changes identified\n`;
|
||||
comment += `- [ ] Package structure planned (if applicable)\n`;
|
||||
comment += `- [ ] Multi-tenant implications considered\n`;
|
||||
comment += `- [ ] Permission levels defined\n`;
|
||||
comment += `- [ ] Declarative approach preferred over imperative\n`;
|
||||
comment += `- [ ] Component size kept under 150 LOC\n`;
|
||||
comment += `- [ ] Security implications reviewed\n`;
|
||||
comment += `- [ ] Testing strategy outlined\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** can help implement this feature following these architectural principles.\n\n`;
|
||||
comment += `📖 See [Copilot Instructions](/.github/copilot-instructions.md) for development guidelines.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
prd-check:
|
||||
name: Check PRD Alignment
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'enhancement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PRD for similar features
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const issue = context.payload.issue;
|
||||
|
||||
try {
|
||||
const prd = fs.readFileSync('docs/getting-started/PRD.md', 'utf8');
|
||||
|
||||
// Extract key terms from issue
|
||||
const issueText = (issue.title + ' ' + issue.body).toLowerCase();
|
||||
const keywords = ['level', 'god', 'tenant', 'package', 'component', 'workflow', 'lua', 'declarative'];
|
||||
|
||||
const foundKeywords = keywords.filter(k => issueText.includes(k));
|
||||
|
||||
let comment = `## 📋 PRD Alignment Check\n\n`;
|
||||
|
||||
if (foundKeywords.length > 0) {
|
||||
comment += `This feature relates to the following PRD concepts: **${foundKeywords.join(', ')}**\n\n`;
|
||||
comment += `Please review [docs/getting-started/PRD.md](/docs/getting-started/PRD.md) to ensure alignment with the project mission and existing features.\n\n`;
|
||||
}
|
||||
|
||||
comment += `### 🎯 Mission Statement\n\n`;
|
||||
comment += `MetaBuilder aims to be a "fully declarative, procedurally-generated multi-tenant application platform where 95% of functionality is defined through JSON and Lua."\n\n`;
|
||||
comment += `Does this feature support that mission? If so, how?\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** Review the PRD and suggest implementation approach.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not read PRD.md:', e.message);
|
||||
}
|
||||
|
||||
suggest-implementation:
|
||||
name: Suggest Implementation Approach
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
github.event.label.name == 'ready-to-implement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Generate implementation suggestion
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let comment = `## 🛠️ Implementation Guidance\n\n`;
|
||||
comment += `This issue is ready for implementation! Here's a suggested approach:\n\n`;
|
||||
|
||||
comment += `### 📝 Step-by-Step Plan\n\n`;
|
||||
comment += `1. **Planning Phase**\n`;
|
||||
comment += ` - [ ] Review PRD.md and update if needed\n`;
|
||||
comment += ` - [ ] Check existing package structure\n`;
|
||||
comment += ` - [ ] Design database schema changes (if any)\n`;
|
||||
comment += ` - [ ] Sketch component hierarchy\n\n`;
|
||||
|
||||
comment += `2. **Database Phase**\n`;
|
||||
comment += ` - [ ] Update \`prisma/schema.prisma\`\n`;
|
||||
comment += ` - [ ] Run \`bun run db:generate\`\n`;
|
||||
comment += ` - [ ] Create or update seed data\n`;
|
||||
comment += ` - [ ] Test database operations\n\n`;
|
||||
|
||||
comment += `3. **Implementation Phase**\n`;
|
||||
comment += ` - [ ] Create package structure (if new package)\n`;
|
||||
comment += ` - [ ] Build generic renderers (prefer over specific components)\n`;
|
||||
comment += ` - [ ] Add Lua scripts for business logic\n`;
|
||||
comment += ` - [ ] Wire up UI components\n`;
|
||||
comment += ` - [ ] Ensure components are <150 LOC\n\n`;
|
||||
|
||||
comment += `4. **Testing Phase**\n`;
|
||||
comment += ` - [ ] Run \`bun run lint\` and fix issues\n`;
|
||||
comment += ` - [ ] Add E2E tests in \`e2e/\` directory\n`;
|
||||
comment += ` - [ ] Test at all permission levels\n`;
|
||||
comment += ` - [ ] Verify multi-tenant isolation\n`;
|
||||
comment += ` - [ ] Test package import/export\n\n`;
|
||||
|
||||
comment += `5. **Documentation Phase**\n`;
|
||||
comment += ` - [ ] Update PRD.md with feature details\n`;
|
||||
comment += ` - [ ] Document Lua APIs if new\n`;
|
||||
comment += ` - [ ] Add usage examples\n`;
|
||||
comment += ` - [ ] Update workflow docs if needed\n\n`;
|
||||
|
||||
comment += `### 🤖 Copilot Assistance\n\n`;
|
||||
comment += `**@copilot** can help with:\n`;
|
||||
comment += `- Generating Prisma schema definitions\n`;
|
||||
comment += `- Creating seed data JSON structures\n`;
|
||||
comment += `- Writing Lua script templates\n`;
|
||||
comment += `- Building generic component renderers\n`;
|
||||
comment += `- Writing E2E tests\n\n`;
|
||||
|
||||
comment += `### 🔗 Useful Resources\n\n`;
|
||||
comment += `- [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
comment += `- [PRD](/.github/../PRD.md)\n`;
|
||||
comment += `- [Workflow Testing](/.github/workflows/README.md)\n`;
|
||||
comment += `- [Package Structure](/packages/)\n\n`;
|
||||
|
||||
comment += `Ready to start? Create a branch: \`feature/issue-${issue.number}\``;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
name: Planning & Design
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
architecture-review:
|
||||
name: Architecture & Design Review
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
(github.event.label.name == 'enhancement' || github.event.label.name == 'feature-request')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Review against architecture principles
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title;
|
||||
const body = issue.body || '';
|
||||
|
||||
let suggestions = [];
|
||||
let questions = [];
|
||||
|
||||
// Check if feature aligns with declarative approach
|
||||
if (body.toLowerCase().includes('component') && !body.toLowerCase().includes('json')) {
|
||||
suggestions.push('💡 Consider implementing this as a **declarative component** using JSON configuration and Lua scripts instead of a TypeScript file.');
|
||||
}
|
||||
|
||||
// Check if database schema is mentioned
|
||||
if (!body.toLowerCase().includes('database') && !body.toLowerCase().includes('schema')) {
|
||||
questions.push('🤔 Will this feature require database schema changes? Consider adding Prisma schema details.');
|
||||
}
|
||||
|
||||
// Check if package structure is considered
|
||||
if (body.toLowerCase().includes('new') && !body.toLowerCase().includes('package')) {
|
||||
suggestions.push('📦 This might be a good candidate for a **package-based implementation** with isolated seed data.');
|
||||
}
|
||||
|
||||
// Check for multi-tenant considerations
|
||||
if (!body.toLowerCase().includes('tenant') && !body.toLowerCase().includes('supergod')) {
|
||||
questions.push('🏢 How should this feature work across different **tenants**? Should it be tenant-specific or global?');
|
||||
}
|
||||
|
||||
// Check for permission levels
|
||||
if (!body.toLowerCase().match(/level [1-5]|user|admin|god|supergod/)) {
|
||||
questions.push('🔐 Which **permission levels** should have access to this feature? (user/admin/god/supergod)');
|
||||
}
|
||||
|
||||
// Check for Lua consideration
|
||||
if (body.toLowerCase().includes('logic') && !body.toLowerCase().includes('lua')) {
|
||||
suggestions.push('🌙 Consider implementing business logic in **Lua scripts** for better flexibility and sandboxing.');
|
||||
}
|
||||
|
||||
let comment = `## 🏗️ Architecture Review\n\n`;
|
||||
comment += `Thank you for proposing this enhancement! Here's an architectural review:\n\n`;
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
comment += `### 💡 Architectural Suggestions\n\n`;
|
||||
suggestions.forEach(s => comment += `${s}\n\n`);
|
||||
}
|
||||
|
||||
if (questions.length > 0) {
|
||||
comment += `### 🤔 Questions to Consider\n\n`;
|
||||
questions.forEach(q => comment += `${q}\n\n`);
|
||||
}
|
||||
|
||||
comment += `### ✅ Design Checklist\n\n`;
|
||||
comment += `- [ ] Database schema changes identified\n`;
|
||||
comment += `- [ ] Package structure planned (if applicable)\n`;
|
||||
comment += `- [ ] Multi-tenant implications considered\n`;
|
||||
comment += `- [ ] Permission levels defined\n`;
|
||||
comment += `- [ ] Declarative approach preferred over imperative\n`;
|
||||
comment += `- [ ] Component size kept under 150 LOC\n`;
|
||||
comment += `- [ ] Security implications reviewed\n`;
|
||||
comment += `- [ ] Testing strategy outlined\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** can help implement this feature following these architectural principles.\n\n`;
|
||||
comment += `📖 See [Copilot Instructions](/.github/copilot-instructions.md) for development guidelines.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
prd-check:
|
||||
name: Check PRD Alignment
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'enhancement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PRD for similar features
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const issue = context.payload.issue;
|
||||
|
||||
try {
|
||||
const prd = fs.readFileSync('docs/getting-started/PRD.md', 'utf8');
|
||||
|
||||
// Extract key terms from issue
|
||||
const issueText = (issue.title + ' ' + issue.body).toLowerCase();
|
||||
const keywords = ['level', 'god', 'tenant', 'package', 'component', 'workflow', 'lua', 'declarative'];
|
||||
|
||||
const foundKeywords = keywords.filter(k => issueText.includes(k));
|
||||
|
||||
let comment = `## 📋 PRD Alignment Check\n\n`;
|
||||
|
||||
if (foundKeywords.length > 0) {
|
||||
comment += `This feature relates to the following PRD concepts: **${foundKeywords.join(', ')}**\n\n`;
|
||||
comment += `Please review [docs/getting-started/PRD.md](/docs/getting-started/PRD.md) to ensure alignment with the project mission and existing features.\n\n`;
|
||||
}
|
||||
|
||||
comment += `### 🎯 Mission Statement\n\n`;
|
||||
comment += `MetaBuilder aims to be a "fully declarative, procedurally-generated multi-tenant application platform where 95% of functionality is defined through JSON and Lua."\n\n`;
|
||||
comment += `Does this feature support that mission? If so, how?\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** Review the PRD and suggest implementation approach.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not read PRD.md:', e.message);
|
||||
}
|
||||
|
||||
suggest-implementation:
|
||||
name: Suggest Implementation Approach
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
github.event.label.name == 'ready-to-implement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Generate implementation suggestion
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let comment = `## 🛠️ Implementation Guidance\n\n`;
|
||||
comment += `This issue is ready for implementation! Here's a suggested approach:\n\n`;
|
||||
|
||||
comment += `### 📝 Step-by-Step Plan\n\n`;
|
||||
comment += `1. **Planning Phase**\n`;
|
||||
comment += ` - [ ] Review PRD.md and update if needed\n`;
|
||||
comment += ` - [ ] Check existing package structure\n`;
|
||||
comment += ` - [ ] Design database schema changes (if any)\n`;
|
||||
comment += ` - [ ] Sketch component hierarchy\n\n`;
|
||||
|
||||
comment += `2. **Database Phase**\n`;
|
||||
comment += ` - [ ] Update \`prisma/schema.prisma\`\n`;
|
||||
comment += ` - [ ] Run \`bun run db:generate\`\n`;
|
||||
comment += ` - [ ] Create or update seed data\n`;
|
||||
comment += ` - [ ] Test database operations\n\n`;
|
||||
|
||||
comment += `3. **Implementation Phase**\n`;
|
||||
comment += ` - [ ] Create package structure (if new package)\n`;
|
||||
comment += ` - [ ] Build generic renderers (prefer over specific components)\n`;
|
||||
comment += ` - [ ] Add Lua scripts for business logic\n`;
|
||||
comment += ` - [ ] Wire up UI components\n`;
|
||||
comment += ` - [ ] Ensure components are <150 LOC\n\n`;
|
||||
|
||||
comment += `4. **Testing Phase**\n`;
|
||||
comment += ` - [ ] Run \`bun run lint\` and fix issues\n`;
|
||||
comment += ` - [ ] Add E2E tests in \`e2e/\` directory\n`;
|
||||
comment += ` - [ ] Test at all permission levels\n`;
|
||||
comment += ` - [ ] Verify multi-tenant isolation\n`;
|
||||
comment += ` - [ ] Test package import/export\n\n`;
|
||||
|
||||
comment += `5. **Documentation Phase**\n`;
|
||||
comment += ` - [ ] Update PRD.md with feature details\n`;
|
||||
comment += ` - [ ] Document Lua APIs if new\n`;
|
||||
comment += ` - [ ] Add usage examples\n`;
|
||||
comment += ` - [ ] Update workflow docs if needed\n\n`;
|
||||
|
||||
comment += `### 🤖 Copilot Assistance\n\n`;
|
||||
comment += `**@copilot** can help with:\n`;
|
||||
comment += `- Generating Prisma schema definitions\n`;
|
||||
comment += `- Creating seed data JSON structures\n`;
|
||||
comment += `- Writing Lua script templates\n`;
|
||||
comment += `- Building generic component renderers\n`;
|
||||
comment += `- Writing E2E tests\n\n`;
|
||||
|
||||
comment += `### 🔗 Useful Resources\n\n`;
|
||||
comment += `- [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
comment += `- [PRD](/.github/../PRD.md)\n`;
|
||||
comment += `- [Workflow Testing](/.github/workflows/README.md)\n`;
|
||||
comment += `- [Package Structure](/packages/)\n\n`;
|
||||
|
||||
comment += `Ready to start? Create a branch: \`feature/issue-${issue.number}\``;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
1332
.github/workflows/quality/quality-metrics.yml
vendored
1332
.github/workflows/quality/quality-metrics.yml
vendored
File diff suppressed because it is too large
Load Diff
184
.github/workflows/quality/size-limits.yml
vendored
184
.github/workflows/quality/size-limits.yml
vendored
@@ -1,92 +1,92 @@
|
||||
name: Code Size Limits
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
- 'tools/enforce-size-limits.ts'
|
||||
- '.github/workflows/size-limits.yml'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
|
||||
jobs:
|
||||
size-limits:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Check code size limits
|
||||
run: bunx tsx ../../tools/enforce-size-limits.ts
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: size-limits-report
|
||||
path: frontends/nextjs/size-limits-report.json
|
||||
retention-days: 7
|
||||
|
||||
- name: Comment on PR
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const report = JSON.parse(fs.readFileSync('frontends/nextjs/size-limits-report.json', 'utf8'));
|
||||
|
||||
let comment = '## 📏 Code Size Limits\n\n';
|
||||
|
||||
if (report.errors === 0 && report.warnings === 0) {
|
||||
comment += '✅ All files pass size limits!';
|
||||
} else {
|
||||
if (report.errors > 0) {
|
||||
comment += `### ❌ Errors (${report.errors})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'error')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
if (report.warnings > 0) {
|
||||
comment += `\n### ⚠️ Warnings (${report.warnings})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'warning')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
comment += '\n[See refactoring guide →](../blob/main/docs/REFACTORING_ENFORCEMENT_GUIDE.md)';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
name: Code Size Limits
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
- 'tools/enforce-size-limits.ts'
|
||||
- '.github/workflows/size-limits.yml'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
|
||||
jobs:
|
||||
size-limits:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: '1.3.4'
|
||||
|
||||
- name: Cache Bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: bun-deps-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.bun
|
||||
restore-keys: bun-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Check code size limits
|
||||
run: bunx tsx ../../tools/enforce-size-limits.ts
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: size-limits-report
|
||||
path: frontends/nextjs/size-limits-report.json
|
||||
retention-days: 7
|
||||
|
||||
- name: Comment on PR
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const report = JSON.parse(fs.readFileSync('frontends/nextjs/size-limits-report.json', 'utf8'));
|
||||
|
||||
let comment = '## 📏 Code Size Limits\n\n';
|
||||
|
||||
if (report.errors === 0 && report.warnings === 0) {
|
||||
comment += '✅ All files pass size limits!';
|
||||
} else {
|
||||
if (report.errors > 0) {
|
||||
comment += `### ❌ Errors (${report.errors})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'error')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
if (report.warnings > 0) {
|
||||
comment += `\n### ⚠️ Warnings (${report.warnings})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'warning')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
comment += '\n[See refactoring guide →](../blob/main/docs/REFACTORING_ENFORCEMENT_GUIDE.md)';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
324
.github/workflows/todo-to-issues.yml
vendored
324
.github/workflows/todo-to-issues.yml
vendored
@@ -1,162 +1,162 @@
|
||||
name: TODO to Issues Sync
|
||||
|
||||
# This workflow can be triggered manually to convert TODO items to GitHub issues
|
||||
# or can be run on a schedule to keep issues in sync with TODO files
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: 'Execution mode'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dry-run
|
||||
- export-json
|
||||
- create-issues
|
||||
default: 'dry-run'
|
||||
|
||||
filter_priority:
|
||||
description: 'Filter by priority (leave empty for all)'
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- ''
|
||||
- critical
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
|
||||
filter_label:
|
||||
description: 'Filter by label (e.g., security, frontend)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
exclude_checklist:
|
||||
description: 'Exclude checklist items'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
limit:
|
||||
description: 'Limit number of issues (0 for no limit)'
|
||||
required: false
|
||||
type: number
|
||||
default: 0
|
||||
|
||||
# Uncomment to run on a schedule (e.g., weekly)
|
||||
# schedule:
|
||||
# - cron: '0 0 * * 0' # Every Sunday at midnight
|
||||
|
||||
jobs:
|
||||
convert-todos:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y
|
||||
|
||||
- name: Authenticate GitHub CLI
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "$GH_TOKEN" | gh auth login --with-token
|
||||
gh auth status
|
||||
|
||||
- name: Build command arguments
|
||||
id: args
|
||||
run: |
|
||||
ARGS=""
|
||||
|
||||
# Add mode
|
||||
if [ "${{ inputs.mode }}" = "dry-run" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
elif [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
ARGS="$ARGS --output todos-export.json"
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
ARGS="$ARGS --create"
|
||||
fi
|
||||
|
||||
# Add filters
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
ARGS="$ARGS --filter-priority ${{ inputs.filter_priority }}"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
ARGS="$ARGS --filter-label ${{ inputs.filter_label }}"
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
ARGS="$ARGS --exclude-checklist"
|
||||
fi
|
||||
|
||||
# Add limit if specified
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
ARGS="$ARGS --limit ${{ inputs.limit }}"
|
||||
fi
|
||||
|
||||
echo "args=$ARGS" >> $GITHUB_OUTPUT
|
||||
echo "Command arguments: $ARGS"
|
||||
|
||||
- name: Run populate-kanban script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
python3 tools/project-management/populate-kanban.py ${{ steps.args.outputs.args }}
|
||||
|
||||
- name: Upload JSON export (if applicable)
|
||||
if: inputs.mode == 'export-json'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: todos-export
|
||||
path: todos-export.json
|
||||
retention-days: 30
|
||||
|
||||
- name: Create summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## TODO to Issues Conversion" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Mode:** ${{ inputs.mode }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
echo "**Priority Filter:** ${{ inputs.filter_priority }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
echo "**Label Filter:** ${{ inputs.filter_label }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
echo "**Checklist Items:** Excluded" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
echo "**Limit:** ${{ inputs.limit }} items" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
echo "✅ JSON export created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download the artifact from the workflow run page" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
echo "✅ GitHub issues created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "View issues: https://github.com/${{ github.repository }}/issues" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "ℹ️ Dry run completed - no issues created" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
name: TODO to Issues Sync
|
||||
|
||||
# This workflow can be triggered manually to convert TODO items to GitHub issues
|
||||
# or can be run on a schedule to keep issues in sync with TODO files
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: 'Execution mode'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dry-run
|
||||
- export-json
|
||||
- create-issues
|
||||
default: 'dry-run'
|
||||
|
||||
filter_priority:
|
||||
description: 'Filter by priority (leave empty for all)'
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- ''
|
||||
- critical
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
|
||||
filter_label:
|
||||
description: 'Filter by label (e.g., security, frontend)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
exclude_checklist:
|
||||
description: 'Exclude checklist items'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
limit:
|
||||
description: 'Limit number of issues (0 for no limit)'
|
||||
required: false
|
||||
type: number
|
||||
default: 0
|
||||
|
||||
# Uncomment to run on a schedule (e.g., weekly)
|
||||
# schedule:
|
||||
# - cron: '0 0 * * 0' # Every Sunday at midnight
|
||||
|
||||
jobs:
|
||||
convert-todos:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y
|
||||
|
||||
- name: Authenticate GitHub CLI
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "$GH_TOKEN" | gh auth login --with-token
|
||||
gh auth status
|
||||
|
||||
- name: Build command arguments
|
||||
id: args
|
||||
run: |
|
||||
ARGS=""
|
||||
|
||||
# Add mode
|
||||
if [ "${{ inputs.mode }}" = "dry-run" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
elif [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
ARGS="$ARGS --output todos-export.json"
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
ARGS="$ARGS --create"
|
||||
fi
|
||||
|
||||
# Add filters
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
ARGS="$ARGS --filter-priority ${{ inputs.filter_priority }}"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
ARGS="$ARGS --filter-label ${{ inputs.filter_label }}"
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
ARGS="$ARGS --exclude-checklist"
|
||||
fi
|
||||
|
||||
# Add limit if specified
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
ARGS="$ARGS --limit ${{ inputs.limit }}"
|
||||
fi
|
||||
|
||||
echo "args=$ARGS" >> $GITHUB_OUTPUT
|
||||
echo "Command arguments: $ARGS"
|
||||
|
||||
- name: Run populate-kanban script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
python3 tools/project-management/populate-kanban.py ${{ steps.args.outputs.args }}
|
||||
|
||||
- name: Upload JSON export (if applicable)
|
||||
if: inputs.mode == 'export-json'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: todos-export
|
||||
path: todos-export.json
|
||||
retention-days: 30
|
||||
|
||||
- name: Create summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## TODO to Issues Conversion" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Mode:** ${{ inputs.mode }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
echo "**Priority Filter:** ${{ inputs.filter_priority }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
echo "**Label Filter:** ${{ inputs.filter_label }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
echo "**Checklist Items:** Excluded" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
echo "**Limit:** ${{ inputs.limit }} items" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
echo "✅ JSON export created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download the artifact from the workflow run page" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
echo "✅ GitHub issues created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "View issues: https://github.com/${{ github.repository }}/issues" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "ℹ️ Dry run completed - no issues created" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
396
.github/workflows/triage.yml
vendored
396
.github/workflows/triage.yml
vendored
@@ -1,198 +1,198 @@
|
||||
name: Issue and PR Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, reopened]
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage Issues
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Categorize and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = (issue.title || '').toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = `${title}\n${body}`;
|
||||
|
||||
const labels = new Set();
|
||||
const missing = [];
|
||||
|
||||
const typeMatchers = [
|
||||
{ regex: /bug|error|crash|broken|fail/, label: 'bug' },
|
||||
{ regex: /feature|enhancement|add|new|implement/, label: 'enhancement' },
|
||||
{ regex: /document|readme|docs|guide/, label: 'documentation' },
|
||||
{ regex: /test|testing|spec|e2e/, label: 'testing' },
|
||||
{ regex: /security|vulnerability|exploit|xss|sql/, label: 'security' },
|
||||
{ regex: /performance|slow|optimize|speed/, label: 'performance' },
|
||||
];
|
||||
|
||||
for (const match of typeMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
const areaMatchers = [
|
||||
{ regex: /frontend|react|next|ui|component|browser/, label: 'area: frontend' },
|
||||
{ regex: /api|backend|service|server/, label: 'area: backend' },
|
||||
{ regex: /database|prisma|schema|sql/, label: 'area: database' },
|
||||
{ regex: /workflow|github actions|ci|pipeline/, label: 'area: workflows' },
|
||||
{ regex: /docs|readme|guide/, label: 'area: documentation' },
|
||||
];
|
||||
|
||||
for (const match of areaMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.add('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.add('priority: low');
|
||||
} else {
|
||||
labels.add('priority: medium');
|
||||
}
|
||||
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.size <= 2) {
|
||||
labels.add('good first issue');
|
||||
}
|
||||
|
||||
const reproductionHints = ['steps to reproduce', 'expected', 'actual'];
|
||||
for (const hint of reproductionHints) {
|
||||
if (!body.includes(hint)) {
|
||||
missing.push(hint);
|
||||
}
|
||||
}
|
||||
|
||||
const supportInfo = body.includes('version') || body.match(/v\d+\.\d+/);
|
||||
if (!supportInfo) {
|
||||
missing.push('version information');
|
||||
}
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const checklist = missing.map(item => `- [ ] Add ${item}`).join('\n') || '- [x] Description includes key details.';
|
||||
const summary = Array.from(labels).map(l => `- ${l}`).join('\n') || '- No labels inferred yet.';
|
||||
|
||||
const comment = [
|
||||
'👋 Thanks for reporting an issue! I ran a quick triage:',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
summary,
|
||||
'',
|
||||
'**Missing details:**',
|
||||
checklist,
|
||||
'',
|
||||
'Adding the missing details will help reviewers respond faster. If the proposed labels look wrong, feel free to update them.',
|
||||
'',
|
||||
'@copilot Please review this triage and refine labels or request any additional context needed—no Codex webhooks involved.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
triage-pr:
|
||||
name: Triage Pull Requests
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Analyze PR files and label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
const labels = new Set();
|
||||
|
||||
const fileFlags = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
docs: files.some(f => f.filename.match(/\.(md|mdx)$/) || f.filename.startsWith('docs/')),
|
||||
frontend: files.some(f => f.filename.includes('frontends/nextjs')),
|
||||
db: files.some(f => f.filename.includes('prisma/') || f.filename.includes('dbal/')),
|
||||
tests: files.some(f => f.filename.match(/(test|spec)\.[jt]sx?/)),
|
||||
};
|
||||
|
||||
if (fileFlags.workflows) labels.add('area: workflows');
|
||||
if (fileFlags.docs) labels.add('area: documentation');
|
||||
if (fileFlags.frontend) labels.add('area: frontend');
|
||||
if (fileFlags.db) labels.add('area: database');
|
||||
if (fileFlags.tests) labels.add('tests');
|
||||
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
const highRiskPaths = files.filter(f => f.filename.includes('.github/workflows') || f.filename.includes('prisma/'));
|
||||
|
||||
let riskLabel = 'risk: low';
|
||||
if (highRiskPaths.length > 0 || totalChanges >= 400) {
|
||||
riskLabel = 'risk: high';
|
||||
} else if (totalChanges >= 150) {
|
||||
riskLabel = 'risk: medium';
|
||||
}
|
||||
labels.add(riskLabel);
|
||||
|
||||
const missing = [];
|
||||
const body = (pr.body || '').toLowerCase();
|
||||
if (!body.includes('test')) missing.push('Test plan');
|
||||
if (fileFlags.frontend && !body.includes('screenshot')) missing.push('Screenshots for UI changes');
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) missing.push('Linked issue reference');
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const labelSummary = Array.from(labels).map(l => `- ${l}`).join('\n');
|
||||
const missingList = missing.length ? missing.map(item => `- [ ] ${item}`).join('\n') : '- [x] Description includes required context.';
|
||||
|
||||
const comment = [
|
||||
'🤖 **Automated PR triage**',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
labelSummary,
|
||||
'',
|
||||
'**Description check:**',
|
||||
missingList,
|
||||
'',
|
||||
'If any labels look incorrect, feel free to adjust them. Closing the missing items will help reviewers move faster.',
|
||||
'',
|
||||
'@copilot Please double-check this triage (no Codex webhook) and add any extra labels or questions for the author.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment,
|
||||
});
|
||||
name: Issue and PR Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, reopened]
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage Issues
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Categorize and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = (issue.title || '').toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = `${title}\n${body}`;
|
||||
|
||||
const labels = new Set();
|
||||
const missing = [];
|
||||
|
||||
const typeMatchers = [
|
||||
{ regex: /bug|error|crash|broken|fail/, label: 'bug' },
|
||||
{ regex: /feature|enhancement|add|new|implement/, label: 'enhancement' },
|
||||
{ regex: /document|readme|docs|guide/, label: 'documentation' },
|
||||
{ regex: /test|testing|spec|e2e/, label: 'testing' },
|
||||
{ regex: /security|vulnerability|exploit|xss|sql/, label: 'security' },
|
||||
{ regex: /performance|slow|optimize|speed/, label: 'performance' },
|
||||
];
|
||||
|
||||
for (const match of typeMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
const areaMatchers = [
|
||||
{ regex: /frontend|react|next|ui|component|browser/, label: 'area: frontend' },
|
||||
{ regex: /api|backend|service|server/, label: 'area: backend' },
|
||||
{ regex: /database|prisma|schema|sql/, label: 'area: database' },
|
||||
{ regex: /workflow|github actions|ci|pipeline/, label: 'area: workflows' },
|
||||
{ regex: /docs|readme|guide/, label: 'area: documentation' },
|
||||
];
|
||||
|
||||
for (const match of areaMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.add('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.add('priority: low');
|
||||
} else {
|
||||
labels.add('priority: medium');
|
||||
}
|
||||
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.size <= 2) {
|
||||
labels.add('good first issue');
|
||||
}
|
||||
|
||||
const reproductionHints = ['steps to reproduce', 'expected', 'actual'];
|
||||
for (const hint of reproductionHints) {
|
||||
if (!body.includes(hint)) {
|
||||
missing.push(hint);
|
||||
}
|
||||
}
|
||||
|
||||
const supportInfo = body.includes('version') || body.match(/v\d+\.\d+/);
|
||||
if (!supportInfo) {
|
||||
missing.push('version information');
|
||||
}
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const checklist = missing.map(item => `- [ ] Add ${item}`).join('\n') || '- [x] Description includes key details.';
|
||||
const summary = Array.from(labels).map(l => `- ${l}`).join('\n') || '- No labels inferred yet.';
|
||||
|
||||
const comment = [
|
||||
'👋 Thanks for reporting an issue! I ran a quick triage:',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
summary,
|
||||
'',
|
||||
'**Missing details:**',
|
||||
checklist,
|
||||
'',
|
||||
'Adding the missing details will help reviewers respond faster. If the proposed labels look wrong, feel free to update them.',
|
||||
'',
|
||||
'@copilot Please review this triage and refine labels or request any additional context needed—no Codex webhooks involved.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
triage-pr:
|
||||
name: Triage Pull Requests
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Analyze PR files and label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
const labels = new Set();
|
||||
|
||||
const fileFlags = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
docs: files.some(f => f.filename.match(/\.(md|mdx)$/) || f.filename.startsWith('docs/')),
|
||||
frontend: files.some(f => f.filename.includes('frontends/nextjs')),
|
||||
db: files.some(f => f.filename.includes('prisma/') || f.filename.includes('dbal/')),
|
||||
tests: files.some(f => f.filename.match(/(test|spec)\.[jt]sx?/)),
|
||||
};
|
||||
|
||||
if (fileFlags.workflows) labels.add('area: workflows');
|
||||
if (fileFlags.docs) labels.add('area: documentation');
|
||||
if (fileFlags.frontend) labels.add('area: frontend');
|
||||
if (fileFlags.db) labels.add('area: database');
|
||||
if (fileFlags.tests) labels.add('tests');
|
||||
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
const highRiskPaths = files.filter(f => f.filename.includes('.github/workflows') || f.filename.includes('prisma/'));
|
||||
|
||||
let riskLabel = 'risk: low';
|
||||
if (highRiskPaths.length > 0 || totalChanges >= 400) {
|
||||
riskLabel = 'risk: high';
|
||||
} else if (totalChanges >= 150) {
|
||||
riskLabel = 'risk: medium';
|
||||
}
|
||||
labels.add(riskLabel);
|
||||
|
||||
const missing = [];
|
||||
const body = (pr.body || '').toLowerCase();
|
||||
if (!body.includes('test')) missing.push('Test plan');
|
||||
if (fileFlags.frontend && !body.includes('screenshot')) missing.push('Screenshots for UI changes');
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) missing.push('Linked issue reference');
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const labelSummary = Array.from(labels).map(l => `- ${l}`).join('\n');
|
||||
const missingList = missing.length ? missing.map(item => `- [ ] ${item}`).join('\n') : '- [x] Description includes required context.';
|
||||
|
||||
const comment = [
|
||||
'🤖 **Automated PR triage**',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
labelSummary,
|
||||
'',
|
||||
'**Description check:**',
|
||||
missingList,
|
||||
'',
|
||||
'If any labels look incorrect, feel free to adjust them. Closing the missing items will help reviewers move faster.',
|
||||
'',
|
||||
'@copilot Please double-check this triage (no Codex webhook) and add any extra labels or questions for the author.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user