Skip to content

Blind 75: Array Product Excluding Current #187

Blind 75: Array Product Excluding Current

Blind 75: Array Product Excluding Current #187

Workflow file for this run

name: Code Quality & Analysis
on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened, labeled]
branches: [main, develop]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
checks: write
issues: write
jobs:
analyze-changed-files:
runs-on: ubuntu-latest
name: Analyze Changed Files
if: github.event_name == 'pull_request' && github.actor == 'pertrai1' && contains(github.event.pull_request.labels.*.name, 'code challenge')
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Get changed files
id: changed-files
run: |
# Get files changed in this PR
git fetch origin ${{ github.base_ref }}
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.(js|ts)$' | tr '\n' ' ')
echo "files=$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "Changed files: $CHANGED_FILES"
- name: Analyze changed files with ESLint
if: steps.changed-files.outputs.files != ''
run: |
FILES="${{ steps.changed-files.outputs.files }}"
if [ -n "$FILES" ]; then
echo "Running ESLint on: $FILES"
# Run ESLint and capture exit code
if npx eslint $FILES --format=json --output-file=eslint-report.json; then
echo "✅ ESLint passed - no errors found"
else
eslint_exit_code=$?
echo "⚠️ ESLint found issues (exit code: $eslint_exit_code)"
# Also run with default formatter for readable output in logs
echo "ESLint issues found in changed files:"
npx eslint $FILES || true
fi
else
echo "No JavaScript/TypeScript files changed"
echo "[]" > eslint-report.json
fi
- name: Format check on changed files
if: steps.changed-files.outputs.files != ''
run: |
FILES="${{ steps.changed-files.outputs.files }}"
if [ -n "$FILES" ]; then
echo "Running Prettier check on: $FILES"
if npx prettier --check $FILES; then
echo "✅ Prettier check passed - all files properly formatted"
else
echo "⚠️ Prettier found formatting issues in changed files"
echo "Run 'npm run format' locally to fix formatting issues"
fi
fi
- name: Run complexity analysis on changed files
if: steps.changed-files.outputs.files != ''
run: |
FILES="${{ steps.changed-files.outputs.files }}"
mkdir -p docs/analysis
mkdir -p analysis-results
# Check if complexity analyzer exists
if [ ! -f "scripts/complexity-analyzer.js" ]; then
echo "⚠️ Warning: Complexity analyzer script not found at scripts/complexity-analyzer.js"
echo "Skipping complexity analysis step"
echo "# Complexity Analysis Unavailable" > analysis-results/analysis-error.md
echo "The complexity analyzer script was not found in this repository." >> analysis-results/analysis-error.md
echo "Please ensure \`scripts/complexity-analyzer.js\` exists to enable algorithm analysis." >> analysis-results/analysis-error.md
exit 0
fi
if [ -n "$FILES" ]; then
echo "Running complexity analysis on changed files..."
analysis_success=0
analysis_total=0
analysis_files_created=""
for file in $FILES; do
if [ -f "$file" ]; then
analysis_total=$((analysis_total + 1))
echo "Analyzing: $file"
# Extract problem name from file path for proper naming
# Examples: leetcode/easy/0205-isomorphic-strings/isomorphic-strings.js -> isomorphic-strings
# Examples: greatfrontend/blind-75/two-sum/solution.js -> two-sum
echo "Checking file pattern for: $file"
if [[ "$file" =~ (leetcode|greatfrontend)/[^/]+/[0-9]+-([^/]+)/([^/]+)\.(js|ts)$ ]]; then
problem_name="${BASH_REMATCH[2]}"
analysis_file="docs/analysis/${problem_name}-analysis.md"
echo "✅ Matched numbered problem pattern. Problem: $problem_name"
elif [[ "$file" =~ (leetcode|greatfrontend)/[^/]+/([^/]+)/([^/]+)\.(js|ts)$ ]]; then
problem_name="${BASH_REMATCH[2]}"
analysis_file="docs/analysis/${problem_name}-analysis.md"
echo "✅ Matched platform pattern. Problem: $problem_name"
echo "Creating analysis file: $analysis_file"
# Run analysis and save to docs/analysis with proper naming
if node scripts/complexity-analyzer.js "$file" > "$analysis_file" 2>&1; then
echo "✅ Successfully analyzed: $file -> $analysis_file"
analysis_success=$((analysis_success + 1))
analysis_files_created="$analysis_files_created $analysis_file"
# Also create a copy in analysis-results for PR comment
cp "$analysis_file" "analysis-results/${problem_name}-analysis.md"
else
echo "❌ Failed to analyze: $file"
# Create error report for this file
cat > "$analysis_file" << EOF
# Analysis Failed for \`$file\`
❌ **Error**: The complexity analysis failed for this file.
**Possible causes:**
- Syntax errors in the code
- Unsupported language constructs
- File encoding issues
**Recommendation**: Check the workflow logs for detailed error information.
EOF
analysis_files_created="$analysis_files_created $analysis_file"
fi
else
echo "⚠️ File does not match expected pattern: $file"
# For non-standard files, use the original logic
base_name=$(basename "$file")
output_name="${base_name%.*}"
if node scripts/complexity-analyzer.js "$file" > "analysis-results/${output_name}.md" 2>&1; then
echo "✅ Successfully analyzed: $file"
analysis_success=$((analysis_success + 1))
else
echo "❌ Failed to analyze: $file"
fi
fi
else
echo "⚠️ File not found: $file"
fi
done
echo "📊 Analysis Summary: $analysis_success/$analysis_total files analyzed successfully"
echo "analysis_files_created=$analysis_files_created" >> $GITHUB_ENV
else
echo "No files to analyze"
fi
- name: Commit and push analysis files
if: steps.changed-files.outputs.files != '' && env.analysis_files_created != ''
run: |
# Configure git
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
# Check if there are any changes to commit
if [ -n "$(git status --porcelain docs/analysis/)" ]; then
echo "📝 Committing analysis files to docs/analysis/"
# Stage only the analysis files we created
git add docs/analysis/
# Commit with descriptive message
git commit -m "📊 Add automated complexity analysis for PR changes
- Generated analysis files for changed solutions
- Files: ${{ steps.changed-files.outputs.files }}
- Timestamp: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
[skip ci]"
# Push to the PR branch
git push origin HEAD:${{ github.head_ref }}
echo "✅ Analysis files committed and pushed successfully"
else
echo "ℹ️ No analysis files to commit"
fi
- name: Generate solution summary
if: steps.changed-files.outputs.files != ''
run: |
cat > solution-analysis.md << 'EOF'
# 🧮 Solution Analysis
**PR:** ${{ github.event.pull_request.title }}
**Files Changed:** ${{ steps.changed-files.outputs.files }}
## 📊 Code Quality Results
### ESLint Analysis
EOF
# Add ESLint results
if [ -f eslint-report.json ]; then
node -e "
const report = JSON.parse(require('fs').readFileSync('eslint-report.json', 'utf8'));
if (report.length === 0) {
console.log('✅ **No ESLint issues found**');
} else {
const totalErrors = report.reduce((sum, file) => sum + file.errorCount, 0);
const totalWarnings = report.reduce((sum, file) => sum + file.warningCount, 0);
console.log(\`- **Errors:** \${totalErrors}\`);
console.log(\`- **Warnings:** \${totalWarnings}\`);
if (totalErrors > 0 || totalWarnings > 0) {
console.log('\\n**Issues by file:**');
report.forEach(file => {
if (file.errorCount > 0 || file.warningCount > 0) {
console.log(\`- \${file.filePath}: \${file.errorCount} errors, \${file.warningCount} warnings\`);
}
});
}
}
" >> solution-analysis.md
fi
echo "" >> solution-analysis.md
echo "### 🔍 Complexity Analysis" >> solution-analysis.md
echo "" >> solution-analysis.md
# Add complexity analysis for each changed file
for file in analysis-results/*.md; do
if [ -f "$file" ]; then
echo "#### $(basename "$file" .md)" >> solution-analysis.md
echo "" >> solution-analysis.md
cat "$file" >> solution-analysis.md
echo "" >> solution-analysis.md
fi
done
# Add tips section
cat >> solution-analysis.md << 'EOF'
## 💡 Analysis Tips
- **Time Complexity**: Focus on the dominant operation in loops
- **Space Complexity**: Consider auxiliary data structures
- **Optimization**: Look for opportunities to improve efficiency
- **Edge Cases**: Ensure your solution handles empty inputs, null/undefined, edge conditions
## 📁 Analysis Files Created
Detailed analysis files have been automatically generated and committed to `docs/analysis/` for future reference.
## 🎯 Next Steps
1. Review any ESLint errors/warnings above
2. Consider the complexity analysis - is this the optimal approach?
3. Test with edge cases mentioned in the problem description
4. Add comments explaining complex logic
5. Check the `docs/analysis/` directory for detailed complexity analysis files
---
*Analysis generated for PR files only*
EOF
- name: Comment PR with analysis
if: steps.changed-files.outputs.files != ''
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Read the analysis report
let analysisContent = 'Analysis report not available';
try {
analysisContent = fs.readFileSync('solution-analysis.md', 'utf8');
} catch (e) {
console.log('Could not read analysis report:', e.message);
analysisContent = `## 🧮 Solution Analysis
❌ Analysis could not be completed. Please check the workflow logs.
**Files attempted:** ${{ steps.changed-files.outputs.files }}`;
}
// Check if we already commented on this PR
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.login === 'github-actions[bot]' &&
comment.body.includes('🧮 Solution Analysis')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: analysisContent
});
console.log('Updated existing PR comment');
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: analysisContent
});
console.log('Created new PR comment');
}
- name: Upload detailed analysis
if: steps.changed-files.outputs.files != ''
uses: actions/upload-artifact@v4
with:
name: solution-analysis-detailed
path: |
solution-analysis.md
analysis-results/
eslint-report.json
retention-days: 30