From 28984bcb6ebe9261a065ba331e451cb34ceb0169 Mon Sep 17 00:00:00 2001 From: lyzno1 Date: Sun, 27 Jul 2025 12:21:33 +0800 Subject: [PATCH 1/2] feat(ci): comprehensive CI/CD workflows and improved PR template - Add main CI/CD pipeline with smart change detection - Add dependency update automation with security audit - Add code quality analysis with complexity tracking - Enhance security checks to run on PRs - Simplify PR template with consolidated checklists - Add comprehensive workflow documentation All workflows use pnpm and follow project conventions --- .github/PULL_REQUEST_TEMPLATE.md | 72 ++++- .github/workflows/README.md | 243 +++++++++++++++++ .github/workflows/ci.yml | 323 ++++++++++++++++++++++ .github/workflows/code-quality.yml | 349 ++++++++++++++++++++++++ .github/workflows/dependency-update.yml | 222 +++++++++++++++ .github/workflows/security.yml | 2 + 6 files changed, 1201 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/code-quality.yml create mode 100644 .github/workflows/dependency-update.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index db5de18e..8411471b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,32 +3,84 @@ Brief description of what this PR does. Fixes #(issue number) +Related to #(issue number) ## Type of Change -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] Documentation update -- [ ] Code refactoring -- [ ] Performance improvement +- [ ] ๐Ÿ› Bug fix (non-breaking change which fixes an issue) +- [ ] โœจ New feature (non-breaking change which adds functionality) +- [ ] ๐Ÿ’ฅ Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] ๐Ÿ“š Documentation update +- [ ] ๐Ÿ”ง Configuration change +- [ ] ๐ŸŽจ Code style/formatting change +- [ ] โ™ป๏ธ Code refactoring +- [ ] โšก Performance improvement +- [ ] ๐Ÿ”’ Security fix +- [ ] ๐ŸŒ Internationalization (i18n) - [ ] Other (please describe): ## Testing -Describe how you tested your changes. +Describe how you tested your changes: + +- [ ] I have tested this change locally +- [ ] I have added unit tests (if applicable) +- [ ] I have tested across different browsers (if applicable) +- [ ] I have tested mobile responsiveness (if applicable) +- [ ] I have tested with different user permissions (if applicable) ## Screenshots (if applicable) Add screenshots here if relevant. -## Checklist +## Quality Checklist + +### Core Requirements - [ ] I have signed the [CLA](../CLA.md) -- [ ] My code follows the project's coding standards +- [ ] Code follows project standards and passes local checks: + - [ ] `pnpm run type-check` passes + - [ ] `pnpm run lint` passes + - [ ] `pnpm run format:check` passes + - [ ] `pnpm run build` succeeds - [ ] I have performed a self-review of my code -- [ ] I have updated documentation if needed +- [ ] My changes generate no new warnings + +### Additional Checks (if applicable) + +- [ ] I18n translations updated (`pnpm run i18n:check` passes) +- [ ] Documentation updated for new features/APIs +- [ ] No hardcoded secrets or performance regressions +- [ ] New dependencies are necessary and secure + +## CI/CD Status + +The following automated checks will run on this PR: + +- โœ… Code formatting and linting +- โœ… TypeScript type checking +- โœ… Build verification +- โœ… Security checks +- โœ… I18n validation (if applicable) +- โœ… Code quality analysis ## Additional Notes Any additional information that reviewers should know about this PR. + +--- + + + +## For Reviewers + +### Focus Areas + + + +### Testing Instructions + + diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 00000000..a1d0d4b0 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,243 @@ +# GitHub Actions Workflows + +This directory contains all automated CI/CD workflows for the AgentifUI project. These workflows ensure code quality, security, and proper testing for every pull request and deployment. + +## ๐Ÿ”„ Available Workflows + +### 1. CI/CD Pipeline (`ci.yml`) + +**Triggers:** Pull requests, pushes to main/master +**Purpose:** Primary quality assurance pipeline + +**Checks:** + +- ๐Ÿ“ Code formatting and linting +- ๐Ÿ” TypeScript type checking +- ๐Ÿ—๏ธ Application build verification +- ๐ŸŒ Internationalization validation +- ๐Ÿ”’ Security scanning +- ๐Ÿ“Š Final status validation + +**Smart Features:** + +- Change detection to skip unnecessary jobs +- Parallel execution for faster feedback +- Caching for improved performance +- Build artifact uploads + +### 2. Security Checks (`security.yml`) + +**Triggers:** PRs, scheduled weekly, manual +**Purpose:** Comprehensive security scanning + +**Checks:** + +- ๐Ÿ” Dependency vulnerability scanning +- ๐Ÿ•ต๏ธ Hardcoded secrets detection +- ๐Ÿ“‹ Security audit reports + +### 3. Code Quality Analysis (`code-quality.yml`) + +**Triggers:** PRs, pushes to main, scheduled weekly +**Purpose:** In-depth code quality assessment + +**Features:** + +- ๐Ÿงฎ Code complexity analysis +- ๐Ÿ“ฆ Bundle size monitoring +- ๐Ÿ“ TypeScript coverage tracking +- ๐Ÿ“š Documentation coverage analysis +- ๐Ÿ’ฌ Automated PR comments with results + +### 4. Dependency Updates (`dependency-update.yml`) + +**Triggers:** Scheduled weekly, manual with options +**Purpose:** Automated dependency management + +**Features:** + +- ๐Ÿ”„ Automated dependency updates (patch/minor/major) +- ๐Ÿงช Post-update validation +- ๐Ÿ“‹ Automatic PR creation +- ๐Ÿ”’ Security audit after updates + +### 5. Claude AI Integration + +**Files:** `claude.yml`, `claude-code-review.yml` +**Purpose:** AI-powered code assistance and review + +## ๐Ÿ“‹ Workflow Requirements + +### Environment Variables for Build + +```yaml +NEXT_PUBLIC_SUPABASE_URL: https://dummy.supabase.co +NEXT_PUBLIC_SUPABASE_ANON_KEY: dummy_key_for_build +``` + +### Required Secrets + +- `ANTHROPIC_API_KEY`: For Claude AI integration +- `GITHUB_TOKEN`: Automatically provided by GitHub + +### Node.js & Package Manager + +- **Node Version:** 18 +- **Package Manager:** pnpm v9 +- **Lock File:** pnpm-lock.yaml (frozen installs) + +## ๐Ÿš€ PR Workflow Process + +When you create a pull request, the following happens automatically: + +1. **Change Detection** ๐Ÿ” + - Analyzes which files changed + - Determines which jobs need to run + - Skips unnecessary checks for efficiency + +2. **Parallel Quality Checks** โšก + - Code formatting and linting + - TypeScript type checking + - Security scanning + - Build verification + +3. **Specialized Validation** ๐ŸŽฏ + - I18n consistency (if translation files changed) + - Code quality analysis (weekly or on-demand) + +4. **Status Reporting** ๐Ÿ“Š + - Clear pass/fail indicators + - Detailed reports as artifacts + - PR comments with quality metrics + +## ๐Ÿ› ๏ธ Local Development Commands + +Before pushing, ensure these commands pass locally: + +```bash +# Type checking +pnpm run type-check + +# Code formatting +pnpm run format:check +pnpm run format # Auto-fix formatting + +# Linting +pnpm run lint + +# Build verification +pnpm run build + +# I18n validation +pnpm run i18n:check +pnpm run i18n:validate +``` + +## ๐Ÿ“ˆ Quality Gates + +### โœ… Required Checks (Must Pass) + +- TypeScript compilation +- Code formatting +- ESLint rules +- Build success +- Security scan (no high/critical vulnerabilities) + +### โš ๏ธ Warning Checks (Should Pass) + +- Code complexity analysis +- Bundle size monitoring +- Documentation coverage +- TypeScript coverage + +## ๐Ÿ”ง Customizing Workflows + +### Adding New Checks + +1. Create new job in appropriate workflow +2. Add step to install dependencies +3. Run your custom checks +4. Upload results as artifacts + +### Modifying Triggers + +```yaml +on: + pull_request: + branches: [master, main, develop] + paths: + - 'app/**' + - 'components/**' + push: + branches: [master, main] + schedule: + - cron: '0 6 * * 0' # Weekly on Sunday +``` + +### Environment Customization + +```yaml +env: + NODE_VERSION: '18' + PNPM_VERSION: '9' + # Add custom environment variables +``` + +## ๐Ÿšจ Troubleshooting + +### Common Issues + +**Build Failures:** + +- Check if all required environment variables are set +- Verify pnpm-lock.yaml is up to date +- Ensure Node.js version matches (18) + +**Type Check Failures:** + +- Run `pnpm run type-check` locally +- Check for missing imports or type definitions +- Verify tsconfig.json is correct + +**Security Scan Failures:** + +- Check for hardcoded secrets in code +- Review dependency vulnerabilities +- Update dependencies if needed + +**I18n Validation Failures:** + +- Ensure all translation keys are consistent +- Check for missing translations +- Validate JSON syntax in message files + +### Getting Help + +1. Check workflow run logs in GitHub Actions tab +2. Download and review artifacts for detailed reports +3. Run commands locally to reproduce issues +4. Check this documentation for configuration details + +## ๐Ÿ“ Workflow Files Overview + +| File | Purpose | When It Runs | +| ------------------------ | ------------------- | ---------------------- | +| `ci.yml` | Main CI/CD pipeline | Every PR, push to main | +| `security.yml` | Security scanning | PRs, weekly, manual | +| `code-quality.yml` | Quality analysis | PRs, pushes, weekly | +| `dependency-update.yml` | Auto-updates | Weekly, manual | +| `claude.yml` | AI assistance | On @claude mentions | +| `claude-code-review.yml` | AI code review | On @claude review | + +## ๐ŸŽฏ Best Practices + +1. **Always run checks locally** before pushing +2. **Keep PRs focused** on single features/fixes +3. **Update documentation** when adding new features +4. **Add tests** for new functionality +5. **Follow commit message conventions** (see git-commit-rule) +6. **Monitor workflow performance** and optimize as needed + +--- + +_This documentation is automatically maintained. Last updated: $(date)_ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..3a242392 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,323 @@ +name: CI/CD Pipeline + +on: + pull_request: + branches: [ master, main, develop ] + push: + branches: [ master, main ] + workflow_dispatch: + +# Cancel previous runs for the same PR/branch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: '18' + PNPM_VERSION: '9' + +jobs: + # Check if files have changed to skip unnecessary jobs + changes: + name: Detect Changes + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + source: ${{ steps.filter.outputs.source }} + docs: ${{ steps.filter.outputs.docs }} + config: ${{ steps.filter.outputs.config }} + i18n: ${{ steps.filter.outputs.i18n }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for file changes + uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + source: + - 'app/**' + - 'components/**' + - 'lib/**' + - 'middleware.ts' + - '*.ts' + - '*.tsx' + - '*.js' + - '*.jsx' + docs: + - 'docs/**' + - '*.md' + config: + - 'package.json' + - 'pnpm-lock.yaml' + - 'tsconfig.json' + - 'next.config.ts' + - 'tailwind.config.js' + - 'eslint.config.mjs' + - 'commitlint.config.mjs' + - 'postcss.config.mjs' + i18n: + - 'messages/**' + - 'i18n/**' + - 'scripts/*i18n*' + + # Install dependencies and cache them + install: + name: Install Dependencies + runs-on: ubuntu-latest + needs: changes + if: needs.changes.outputs.source == 'true' || needs.changes.outputs.config == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pnpm-store + node_modules + key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + + # Code formatting and linting checks + format-and-lint: + name: Format and Lint Check + runs-on: ubuntu-latest + needs: [changes, install] + if: needs.changes.outputs.source == 'true' || needs.changes.outputs.config == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Check code formatting + run: pnpm run format:check + + - name: Run ESLint + run: pnpm run lint + + # TypeScript type checking + type-check: + name: TypeScript Type Check + runs-on: ubuntu-latest + needs: [changes, install] + if: needs.changes.outputs.source == 'true' || needs.changes.outputs.config == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run TypeScript type check + run: pnpm run type-check + + # Internationalization validation + i18n-validation: + name: I18n Validation + runs-on: ubuntu-latest + needs: [changes, install] + if: needs.changes.outputs.i18n == 'true' || needs.changes.outputs.source == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python with uv + uses: astral-sh/setup-uv@v4 + with: + enable-cache: true + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Quick i18n check + run: pnpm run i18n:check + + - name: Validate i18n consistency + run: pnpm run i18n:validate + + # Build the application + build: + name: Build Application + runs-on: ubuntu-latest + needs: [changes, install] + if: needs.changes.outputs.source == 'true' || needs.changes.outputs.config == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build application + run: pnpm run build + env: + # Provide dummy environment variables for build + NEXT_PUBLIC_SUPABASE_URL: https://dummy.supabase.co + NEXT_PUBLIC_SUPABASE_ANON_KEY: dummy_key_for_build + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: .next/ + retention-days: 7 + + # Security checks + security-check: + name: Security Check + runs-on: ubuntu-latest + needs: [changes, install] + if: needs.changes.outputs.source == 'true' || needs.changes.outputs.config == 'true' + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run dependency audit + run: pnpm audit --audit-level=moderate + + - name: Scan for secrets + run: | + echo "Scanning for hardcoded secrets..." + # Check for potential secrets in source code + if grep -r -i -E "(api_key|apikey|secret|token|password)\s*[:=]\s*['\"][a-zA-Z0-9+/]{20,}['\"]" \ + --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" \ + app components lib | grep -v -E "(placeholder|example|test|demo|sample|mock|dummy)"; then + echo "โš ๏ธ Potential hardcoded secret detected" + exit 1 + fi + echo "โœ… No hardcoded secrets found" + + # Final status check - all jobs must pass + ci-status: + name: CI Status Check + runs-on: ubuntu-latest + needs: + - changes + - format-and-lint + - type-check + - i18n-validation + - build + - security-check + if: always() + permissions: + contents: read + steps: + - name: Check all jobs status + run: | + echo "Checking CI pipeline status..." + + # Check if any job failed + if [[ "${{ needs.format-and-lint.result }}" == "failure" ]] || \ + [[ "${{ needs.type-check.result }}" == "failure" ]] || \ + [[ "${{ needs.i18n-validation.result }}" == "failure" ]] || \ + [[ "${{ needs.build.result }}" == "failure" ]] || \ + [[ "${{ needs.security-check.result }}" == "failure" ]]; then + echo "โŒ CI pipeline failed" + exit 1 + fi + + # Check if any required job was skipped when it shouldn't be + if [[ "${{ needs.changes.outputs.source }}" == "true" ]] || [[ "${{ needs.changes.outputs.config }}" == "true" ]]; then + if [[ "${{ needs.format-and-lint.result }}" == "skipped" ]] || \ + [[ "${{ needs.type-check.result }}" == "skipped" ]] || \ + [[ "${{ needs.build.result }}" == "skipped" ]] || \ + [[ "${{ needs.security-check.result }}" == "skipped" ]]; then + echo "โŒ Required job was skipped" + exit 1 + fi + fi + + echo "โœ… All CI checks passed successfully" \ No newline at end of file diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 00000000..e4aa7555 --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,349 @@ +name: Code Quality Analysis + +on: + pull_request: + branches: [ master, main, develop ] + push: + branches: [ master, main ] + schedule: + # Run weekly on Sunday at 6:00 AM UTC + - cron: '0 6 * * 0' + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + checks: write + +env: + NODE_VERSION: '18' + PNPM_VERSION: '9' + +jobs: + # Code complexity analysis + complexity-analysis: + name: Code Complexity Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Analyze code complexity + run: | + echo "Analyzing code complexity..." + + # Create complexity report directory + mkdir -p reports + + # Find complex files (> 20 lines per function on average) + echo "## Code Complexity Report" > reports/complexity.md + echo "Generated at: $(date)" >> reports/complexity.md + echo "" >> reports/complexity.md + + # Analyze TypeScript/JavaScript files + find app components lib -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | while read file; do + lines=$(wc -l < "$file") + functions=$(grep -c "function\|=>" "$file" 2>/dev/null || echo 0) + + if [ "$functions" -gt 0 ]; then + complexity=$((lines / functions)) + if [ "$complexity" -gt 20 ]; then + echo "โš ๏ธ **$file**: $complexity lines/function (total: $lines lines, $functions functions)" >> reports/complexity.md + fi + fi + done + + # Check if any complex files found + if ! grep -q "โš ๏ธ" reports/complexity.md; then + echo "โœ… No overly complex files detected" >> reports/complexity.md + fi + + - name: Upload complexity report + uses: actions/upload-artifact@v4 + with: + name: complexity-report + path: reports/complexity.md + retention-days: 30 + + # Bundle size analysis + bundle-analysis: + name: Bundle Size Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build and analyze bundle + run: | + echo "Building application for bundle analysis..." + pnpm run build + env: + NEXT_PUBLIC_SUPABASE_URL: https://dummy.supabase.co + NEXT_PUBLIC_SUPABASE_ANON_KEY: dummy_key_for_build + ANALYZE: true + + - name: Analyze bundle size + run: | + echo "Analyzing bundle size..." + mkdir -p reports + + # Check .next directory size + if [ -d ".next" ]; then + echo "## Bundle Size Report" > reports/bundle-size.md + echo "Generated at: $(date)" >> reports/bundle-size.md + echo "" >> reports/bundle-size.md + + # Total build size + total_size=$(du -sh .next | cut -f1) + echo "**Total build size:** $total_size" >> reports/bundle-size.md + echo "" >> reports/bundle-size.md + + # Static directory size + if [ -d ".next/static" ]; then + static_size=$(du -sh .next/static | cut -f1) + echo "**Static assets size:** $static_size" >> reports/bundle-size.md + fi + + # Find large files (> 1MB) + echo "" >> reports/bundle-size.md + echo "### Large Files (> 1MB)" >> reports/bundle-size.md + find .next -type f -size +1M -exec ls -lh {} \; | \ + awk '{print "- " $9 ": " $5}' >> reports/bundle-size.md || \ + echo "No large files found" >> reports/bundle-size.md + fi + + - name: Upload bundle analysis + uses: actions/upload-artifact@v4 + with: + name: bundle-analysis + path: reports/bundle-size.md + retention-days: 30 + + # Type coverage analysis + type-coverage: + name: TypeScript Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Analyze TypeScript usage + run: | + echo "Analyzing TypeScript coverage..." + mkdir -p reports + + echo "## TypeScript Coverage Report" > reports/type-coverage.md + echo "Generated at: $(date)" >> reports/type-coverage.md + echo "" >> reports/type-coverage.md + + # Count file types + ts_files=$(find app components lib -name "*.ts" | wc -l) + tsx_files=$(find app components lib -name "*.tsx" | wc -l) + js_files=$(find app components lib -name "*.js" | wc -l) + jsx_files=$(find app components lib -name "*.jsx" | wc -l) + + total_files=$((ts_files + tsx_files + js_files + jsx_files)) + ts_total=$((ts_files + tsx_files)) + + if [ $total_files -gt 0 ]; then + coverage=$((ts_total * 100 / total_files)) + echo "**TypeScript Coverage:** $coverage% ($ts_total/$total_files files)" >> reports/type-coverage.md + echo "" >> reports/type-coverage.md + echo "- TypeScript files: $ts_files" >> reports/type-coverage.md + echo "- TSX files: $tsx_files" >> reports/type-coverage.md + echo "- JavaScript files: $js_files" >> reports/type-coverage.md + echo "- JSX files: $jsx_files" >> reports/type-coverage.md + + # Warn if coverage is low + if [ $coverage -lt 80 ]; then + echo "" >> reports/type-coverage.md + echo "โš ๏ธ **Warning:** TypeScript coverage is below 80%" >> reports/type-coverage.md + fi + fi + + - name: Check for any type issues + run: | + echo "Checking for TypeScript issues..." + pnpm run type-check 2>&1 | tee type-check.log || true + + # Add results to report + echo "" >> reports/type-coverage.md + echo "### Type Check Results" >> reports/type-coverage.md + if grep -q "error" type-check.log; then + echo "โŒ Type errors found:" >> reports/type-coverage.md + echo '```' >> reports/type-coverage.md + cat type-check.log >> reports/type-coverage.md + echo '```' >> reports/type-coverage.md + else + echo "โœ… No type errors found" >> reports/type-coverage.md + fi + + - name: Upload type coverage report + uses: actions/upload-artifact@v4 + with: + name: type-coverage-report + path: reports/type-coverage.md + retention-days: 30 + + # Documentation coverage + docs-coverage: + name: Documentation Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Analyze documentation coverage + run: | + echo "Analyzing documentation coverage..." + mkdir -p reports + + echo "## Documentation Coverage Report" > reports/docs-coverage.md + echo "Generated at: $(date)" >> reports/docs-coverage.md + echo "" >> reports/docs-coverage.md + + # Count functions without JSDoc comments + undocumented=0 + total_functions=0 + + find app components lib -name "*.ts" -o -name "*.tsx" | while read file; do + # Look for function declarations and exports + grep -n "export.*function\|function.*(" "$file" | while read line; do + line_num=$(echo "$line" | cut -d: -f1) + + # Check if previous line has JSDoc comment + prev_line=$((line_num - 1)) + if [ $prev_line -gt 0 ]; then + prev_content=$(sed -n "${prev_line}p" "$file") + if ! echo "$prev_content" | grep -q "\*\|//"; then + echo "Undocumented function at $file:$line_num" + fi + fi + done + done > undoc_functions.tmp + + undocumented=$(wc -l < undoc_functions.tmp) + + # Count total exported functions + total_functions=$(find app components lib -name "*.ts" -o -name "*.tsx" -exec grep -l "export.*function\|function.*(" {} \; | wc -l) + + if [ $total_functions -gt 0 ]; then + documented=$((total_functions - undocumented)) + coverage=$((documented * 100 / total_functions)) + echo "**Documentation Coverage:** $coverage% ($documented/$total_functions functions)" >> reports/docs-coverage.md + echo "" >> reports/docs-coverage.md + + if [ $undocumented -gt 0 ]; then + echo "### Undocumented Functions" >> reports/docs-coverage.md + cat undoc_functions.tmp >> reports/docs-coverage.md + fi + fi + + rm -f undoc_functions.tmp + + - name: Upload docs coverage report + uses: actions/upload-artifact@v4 + with: + name: docs-coverage-report + path: reports/docs-coverage.md + retention-days: 30 + + # Generate quality summary + quality-summary: + name: Quality Summary + runs-on: ubuntu-latest + needs: [complexity-analysis, bundle-analysis, type-coverage, docs-coverage] + if: always() + steps: + - name: Download all reports + uses: actions/download-artifact@v4 + with: + path: reports + + - name: Generate summary + run: | + echo "Generating code quality summary..." + + echo "# Code Quality Summary" > quality-summary.md + echo "Generated at: $(date)" >> quality-summary.md + echo "" >> quality-summary.md + + # Add all individual reports + for report in reports/*/; do + if [ -f "$report"/*.md ]; then + echo "---" >> quality-summary.md + cat "$report"/*.md >> quality-summary.md + echo "" >> quality-summary.md + fi + done + + - name: Upload quality summary + uses: actions/upload-artifact@v4 + with: + name: quality-summary + path: quality-summary.md + retention-days: 30 + + - name: Comment on PR (if applicable) + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + try { + const summary = fs.readFileSync('quality-summary.md', 'utf8'); + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `## ๐Ÿ“Š Code Quality Analysis Results\n\n${summary}\n\n---\n*This comment was generated automatically by the code quality workflow.*` + }); + } catch (error) { + console.log('Could not create PR comment:', error.message); + } \ No newline at end of file diff --git a/.github/workflows/dependency-update.yml b/.github/workflows/dependency-update.yml new file mode 100644 index 00000000..1990d52b --- /dev/null +++ b/.github/workflows/dependency-update.yml @@ -0,0 +1,222 @@ +name: Dependency Update + +on: + schedule: + # Run every Monday at 9:00 AM UTC + - cron: '0 9 * * 1' + workflow_dispatch: + inputs: + update_type: + description: 'Type of dependencies to update' + required: true + default: 'minor' + type: choice + options: + - patch + - minor + - major + +permissions: + contents: write + pull-requests: write + +env: + NODE_VERSION: '18' + PNPM_VERSION: '9' + +jobs: + # Check for outdated dependencies + check-dependencies: + name: Check Dependencies + runs-on: ubuntu-latest + outputs: + has-updates: ${{ steps.check.outputs.has-updates }} + update-summary: ${{ steps.check.outputs.update-summary }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Check for outdated dependencies + id: check + run: | + echo "Checking for outdated dependencies..." + + # Get outdated packages + OUTDATED=$(pnpm outdated --format=json 2>/dev/null || echo '{}') + + # Check if there are any updates + if [ "$OUTDATED" = "{}" ]; then + echo "has-updates=false" >> $GITHUB_OUTPUT + echo "update-summary=No outdated dependencies found" >> $GITHUB_OUTPUT + else + echo "has-updates=true" >> $GITHUB_OUTPUT + + # Create summary + echo "update-summary<> $GITHUB_OUTPUT + echo "Found outdated dependencies:" >> $GITHUB_OUTPUT + echo "$OUTDATED" | jq -r 'to_entries[] | "- \(.key): \(.value.current) โ†’ \(.value.latest)"' >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + # Update dependencies based on type + update-dependencies: + name: Update Dependencies + runs-on: ubuntu-latest + needs: check-dependencies + if: needs.check-dependencies.outputs.has-updates == 'true' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Configure Git + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + - name: Update dependencies + run: | + UPDATE_TYPE="${{ github.event.inputs.update_type || 'minor' }}" + echo "Updating $UPDATE_TYPE dependencies..." + + case $UPDATE_TYPE in + patch) + pnpm update --latest-patch + ;; + minor) + pnpm update --latest-minor + ;; + major) + pnpm update --latest + ;; + esac + + - name: Run tests after update + run: | + # Run type check + pnpm run type-check + + # Run build to ensure everything works + pnpm run build + env: + NEXT_PUBLIC_SUPABASE_URL: https://dummy.supabase.co + NEXT_PUBLIC_SUPABASE_ANON_KEY: dummy_key_for_build + + - name: Check for changes + id: changes + run: | + if git diff --quiet; then + echo "No changes to commit" + echo "has-changes=false" >> $GITHUB_OUTPUT + else + echo "Changes detected" + echo "has-changes=true" >> $GITHUB_OUTPUT + fi + + - name: Create Pull Request + if: steps.changes.outputs.has-changes == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: dependency-updates/${{ github.event.inputs.update_type || 'minor' }}-${{ github.run_number }} + title: "chore(deps): update ${{ github.event.inputs.update_type || 'minor' }} dependencies" + body: | + ## Dependency Updates + + This PR updates dependencies to their latest ${{ github.event.inputs.update_type || 'minor' }} versions. + + ### Summary + ${{ needs.check-dependencies.outputs.update-summary }} + + ### Validation + - โœ… TypeScript type check passed + - โœ… Build completed successfully + - โœ… No breaking changes detected + + ### Next Steps + - [ ] Review the changes + - [ ] Test the application locally + - [ ] Merge if everything looks good + + --- + *This PR was created automatically by the dependency update workflow.* + commit-message: "chore(deps): update ${{ github.event.inputs.update_type || 'minor' }} dependencies" + labels: | + dependencies + automated-pr + ${{ github.event.inputs.update_type || 'minor' }}-update + + # Security audit for updated dependencies + security-audit: + name: Security Audit + runs-on: ubuntu-latest + needs: [check-dependencies, update-dependencies] + if: needs.check-dependencies.outputs.has-updates == 'true' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run security audit + run: | + echo "Running security audit..." + pnpm audit --audit-level=moderate + + # Check for high/critical vulnerabilities + if pnpm audit --audit-level=high --json > audit-results.json 2>/dev/null; then + echo "โœ… No high or critical vulnerabilities found" + else + echo "โš ๏ธ High or critical vulnerabilities detected" + cat audit-results.json + exit 1 + fi + + - name: Upload audit results + if: always() + uses: actions/upload-artifact@v4 + with: + name: security-audit-results + path: audit-results.json + retention-days: 7 \ No newline at end of file diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index f8c3c302..946953b7 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -3,6 +3,8 @@ name: Security Checks on: schedule: - cron: '0 2 * * 1' # Run every Monday at 2:00 AM + pull_request: + branches: [ master, main, develop ] workflow_dispatch: permissions: From 32911d49d08cc433a0a1b8ee7bda70ea02201150 Mon Sep 17 00:00:00 2001 From: lyzno1 Date: Sun, 27 Jul 2025 12:32:12 +0800 Subject: [PATCH 2/2] refactor(ci): simplify code quality report for PR comments - Reduce verbose output in PR comments - Only show key metrics: bundle size, TS coverage, complexity count - Keep detailed reports in workflow artifacts - Improve comment readability and usefulness --- .github/workflows/code-quality.yml | 46 +++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index e4aa7555..67004a0d 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -306,20 +306,44 @@ jobs: - name: Generate summary run: | - echo "Generating code quality summary..." + echo "Generating simplified code quality summary..." - echo "# Code Quality Summary" > quality-summary.md - echo "Generated at: $(date)" >> quality-summary.md + echo "## ๐Ÿ“Š Code Quality Summary" > quality-summary.md echo "" >> quality-summary.md - # Add all individual reports - for report in reports/*/; do - if [ -f "$report"/*.md ]; then - echo "---" >> quality-summary.md - cat "$report"/*.md >> quality-summary.md - echo "" >> quality-summary.md + # Bundle size summary + if [ -f "reports/bundle-analysis/bundle-size.md" ]; then + BUNDLE_SIZE=$(grep "Total build size" reports/bundle-analysis/bundle-size.md | cut -d':' -f2 | xargs) + STATIC_SIZE=$(grep "Static assets size" reports/bundle-analysis/bundle-size.md | cut -d':' -f2 | xargs) + echo "### ๐Ÿ“ฆ Bundle Analysis" >> quality-summary.md + echo "- **Total build size:** $BUNDLE_SIZE" >> quality-summary.md + echo "- **Static assets:** $STATIC_SIZE" >> quality-summary.md + echo "" >> quality-summary.md + fi + + # TypeScript coverage + if [ -f "reports/type-coverage-report/type-coverage.md" ]; then + TS_COVERAGE=$(grep "TypeScript Coverage" reports/type-coverage-report/type-coverage.md | head -1) + echo "### ๐Ÿ” TypeScript Coverage" >> quality-summary.md + echo "- $TS_COVERAGE" >> quality-summary.md + echo "" >> quality-summary.md + fi + + # Complexity issues (only show count of complex files) + if [ -f "reports/complexity-report/complexity.md" ]; then + COMPLEX_COUNT=$(grep -c "โš ๏ธ" reports/complexity-report/complexity.md || echo "0") + echo "### โšก Code Complexity" >> quality-summary.md + if [ "$COMPLEX_COUNT" -gt 0 ]; then + echo "- **$COMPLEX_COUNT** files with high complexity (>20 lines/function)" >> quality-summary.md + echo "- Consider refactoring large functions for better maintainability" >> quality-summary.md + else + echo "- โœ… All files have acceptable complexity" >> quality-summary.md fi - done + echo "" >> quality-summary.md + fi + + echo "---" >> quality-summary.md + echo "*Full reports available in workflow artifacts*" >> quality-summary.md - name: Upload quality summary uses: actions/upload-artifact@v4 @@ -342,7 +366,7 @@ jobs: issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - body: `## ๐Ÿ“Š Code Quality Analysis Results\n\n${summary}\n\n---\n*This comment was generated automatically by the code quality workflow.*` + body: `${summary}\n\n*Automated quality analysis - view detailed reports in [workflow artifacts](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})*` }); } catch (error) { console.log('Could not create PR comment:', error.message);