Initial commit
This commit is contained in:
190
scripts/clean-branch.sh
Executable file
190
scripts/clean-branch.sh
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Clean Branch Script
|
||||
# Safely removes common personal development artifacts before PR submission
|
||||
# Part of the open-source-contributions skill
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
echo -e "${BLUE} Clean Branch for PR${NC}"
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Not in a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Interactive mode flag
|
||||
INTERACTIVE=true
|
||||
if [ "$1" = "--non-interactive" ] || [ "$1" = "-y" ]; then
|
||||
INTERACTIVE=false
|
||||
fi
|
||||
|
||||
# Files to potentially remove
|
||||
PERSONAL_FILES=(
|
||||
"SESSION.md"
|
||||
"NOTES.md"
|
||||
"TODO.md"
|
||||
"SCRATCH.md"
|
||||
"DEBUGGING.md"
|
||||
"TESTING.md"
|
||||
)
|
||||
|
||||
FOUND_FILES=()
|
||||
|
||||
echo -e "${BLUE}Scanning for personal development artifacts...${NC}"
|
||||
echo ""
|
||||
|
||||
# Check for personal files
|
||||
for file in "${PERSONAL_FILES[@]}"; do
|
||||
if git ls-files --error-unmatch "$file" > /dev/null 2>&1; then
|
||||
FOUND_FILES+=("$file")
|
||||
echo -e "${YELLOW} Found: $file${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for planning directory
|
||||
if git ls-files | grep -q "^planning/"; then
|
||||
FOUND_FILES+=("planning/")
|
||||
echo -e "${YELLOW} Found: planning/* directory${NC}"
|
||||
git ls-files | grep "^planning/" | head -5 | sed 's/^/ - /'
|
||||
PLANNING_COUNT=$(git ls-files | grep "^planning/" | wc -l)
|
||||
if [ "$PLANNING_COUNT" -gt 5 ]; then
|
||||
echo -e "${YELLOW} ... and $((PLANNING_COUNT - 5)) more files${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for debug screenshots
|
||||
DEBUG_SCREENSHOTS=$(git ls-files | grep -E "(debug|test|scratch).*\.(png|jpg|jpeg|gif)" || true)
|
||||
if [ -n "$DEBUG_SCREENSHOTS" ]; then
|
||||
echo -e "${YELLOW} Found: debug/test screenshots${NC}"
|
||||
echo "$DEBUG_SCREENSHOTS" | sed 's/^/ - /'
|
||||
FOUND_FILES+=("screenshots-debug")
|
||||
fi
|
||||
|
||||
# Check for temporary test files
|
||||
TEMP_TESTS=$(git ls-files | grep -iE "(test-manual|test-debug|quick-test|scratch-test|example-local)" || true)
|
||||
if [ -n "$TEMP_TESTS" ]; then
|
||||
echo -e "${YELLOW} Found: temporary test files${NC}"
|
||||
echo "$TEMP_TESTS" | sed 's/^/ - /'
|
||||
FOUND_FILES+=("temp-tests")
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# If nothing found, exit
|
||||
if [ ${#FOUND_FILES[@]} -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ No personal artifacts found!${NC}"
|
||||
echo -e "${GREEN}Your branch is clean.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Confirm removal
|
||||
if [ "$INTERACTIVE" = true ]; then
|
||||
echo -e "${YELLOW}These files should not be included in your PR.${NC}"
|
||||
echo -e "${BLUE}Would you like to remove them? (y/n)${NC}"
|
||||
read -r response
|
||||
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Cancelled. No files removed.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Removing files...${NC}"
|
||||
|
||||
REMOVED_COUNT=0
|
||||
|
||||
# Remove personal files
|
||||
for file in "${PERSONAL_FILES[@]}"; do
|
||||
if git ls-files --error-unmatch "$file" > /dev/null 2>&1; then
|
||||
git rm --cached "$file" 2>/dev/null || git rm "$file" 2>/dev/null || true
|
||||
echo -e "${GREEN} ✓ Removed: $file${NC}"
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove planning directory
|
||||
if git ls-files | grep -q "^planning/"; then
|
||||
git rm --cached -r "planning/" 2>/dev/null || git rm -r "planning/" 2>/dev/null || true
|
||||
echo -e "${GREEN} ✓ Removed: planning/* directory${NC}"
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
|
||||
# Remove debug screenshots (interactive)
|
||||
if [ -n "$DEBUG_SCREENSHOTS" ]; then
|
||||
if [ "$INTERACTIVE" = true ]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Found debug screenshots. Remove these too? (y/n)${NC}"
|
||||
echo "$DEBUG_SCREENSHOTS" | sed 's/^/ - /'
|
||||
read -r response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
echo "$DEBUG_SCREENSHOTS" | while read -r file; do
|
||||
git rm --cached "$file" 2>/dev/null || git rm "$file" 2>/dev/null || true
|
||||
echo -e "${GREEN} ✓ Removed: $file${NC}"
|
||||
done
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
else
|
||||
echo "$DEBUG_SCREENSHOTS" | while read -r file; do
|
||||
git rm --cached "$file" 2>/dev/null || git rm "$file" 2>/dev/null || true
|
||||
done
|
||||
echo -e "${GREEN} ✓ Removed: debug screenshots${NC}"
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remove temporary test files (interactive)
|
||||
if [ -n "$TEMP_TESTS" ]; then
|
||||
if [ "$INTERACTIVE" = true ]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Found temporary test files. Remove these too? (y/n)${NC}"
|
||||
echo "$TEMP_TESTS" | sed 's/^/ - /'
|
||||
read -r response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
echo "$TEMP_TESTS" | while read -r file; do
|
||||
git rm --cached "$file" 2>/dev/null || git rm "$file" 2>/dev/null || true
|
||||
echo -e "${GREEN} ✓ Removed: $file${NC}"
|
||||
done
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
else
|
||||
echo "$TEMP_TESTS" | while read -r file; do
|
||||
git rm --cached "$file" 2>/dev/null || git rm "$file" 2>/dev/null || true
|
||||
done
|
||||
echo -e "${GREEN} ✓ Removed: temporary test files${NC}"
|
||||
((REMOVED_COUNT++))
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
|
||||
if [ $REMOVED_COUNT -gt 0 ]; then
|
||||
echo -e "${GREEN}✓ Cleaned $REMOVED_COUNT artifact(s)${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Next steps:${NC}"
|
||||
echo -e " 1. Review changes: ${YELLOW}git status${NC}"
|
||||
echo -e " 2. Commit removal: ${YELLOW}git commit -m 'chore: remove personal development artifacts'${NC}"
|
||||
echo -e " 3. Re-run check: ${YELLOW}./scripts/pre-pr-check.sh${NC}"
|
||||
echo -e " 4. Push changes: ${YELLOW}git push${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✓ No files removed${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note:${NC} Files are removed from git tracking but still exist locally."
|
||||
echo -e "Add them to .git/info/exclude to prevent re-adding:"
|
||||
echo ""
|
||||
echo -e "${BLUE}echo 'SESSION.md' >> .git/info/exclude${NC}"
|
||||
echo -e "${BLUE}echo 'planning/' >> .git/info/exclude${NC}"
|
||||
249
scripts/pre-pr-check.sh
Executable file
249
scripts/pre-pr-check.sh
Executable file
@@ -0,0 +1,249 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Pre-PR Check Script
|
||||
# Scans for common personal development artifacts before PR submission
|
||||
# Part of the open-source-contributions skill
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
echo -e "${BLUE} Pre-PR Validation Check${NC}"
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
echo ""
|
||||
|
||||
ERRORS=0
|
||||
WARNINGS=0
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}✗ Not in a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current branch
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
echo -e "${BLUE}Current branch:${NC} $CURRENT_BRANCH"
|
||||
echo ""
|
||||
|
||||
# Check 1: Personal Development Artifacts
|
||||
echo -e "${BLUE}[1/8] Checking for personal development artifacts...${NC}"
|
||||
|
||||
PERSONAL_FILES=(
|
||||
"SESSION.md"
|
||||
"NOTES.md"
|
||||
"TODO.md"
|
||||
"SCRATCH.md"
|
||||
"DEBUGGING.md"
|
||||
"TESTING.md"
|
||||
)
|
||||
|
||||
for file in "${PERSONAL_FILES[@]}"; do
|
||||
if git ls-files --error-unmatch "$file" > /dev/null 2>&1; then
|
||||
echo -e "${RED} ✗ Found: $file (should not be in PR)${NC}"
|
||||
((ERRORS++))
|
||||
fi
|
||||
done
|
||||
|
||||
# Check planning directory
|
||||
if git ls-files | grep -q "^planning/"; then
|
||||
echo -e "${RED} ✗ Found: planning/* directory (should not be in PR)${NC}"
|
||||
git ls-files | grep "^planning/" | head -5 | sed 's/^/ - /'
|
||||
((ERRORS++))
|
||||
fi
|
||||
|
||||
if [ $ERRORS -eq 0 ]; then
|
||||
echo -e "${GREEN} ✓ No personal development artifacts found${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 2: Screenshots and Visual Assets
|
||||
echo -e "${BLUE}[2/8] Checking for debug screenshots...${NC}"
|
||||
|
||||
DEBUG_SCREENSHOTS=$(git ls-files | grep -E "screenshot.*\.(png|jpg|jpeg|gif|mp4|mov)" || true)
|
||||
if [ -n "$DEBUG_SCREENSHOTS" ]; then
|
||||
echo -e "${YELLOW} ⚠ Found screenshots:${NC}"
|
||||
echo "$DEBUG_SCREENSHOTS" | sed 's/^/ - /'
|
||||
echo -e "${YELLOW} → Ensure these are needed for PR description (demonstrating feature)${NC}"
|
||||
echo -e "${YELLOW} → Remove if they're just debugging artifacts${NC}"
|
||||
((WARNINGS++))
|
||||
else
|
||||
echo -e "${GREEN} ✓ No screenshot files found${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 3: Temporary Test Files
|
||||
echo -e "${BLUE}[3/8] Checking for temporary test files...${NC}"
|
||||
|
||||
TEMP_TEST_PATTERNS=(
|
||||
"test-manual"
|
||||
"test-debug"
|
||||
"quick-test"
|
||||
"scratch-test"
|
||||
"example-local"
|
||||
"debug-"
|
||||
"temp-"
|
||||
"tmp-"
|
||||
)
|
||||
|
||||
TEMP_TESTS_FOUND=0
|
||||
for pattern in "${TEMP_TEST_PATTERNS[@]}"; do
|
||||
MATCHES=$(git ls-files | grep -i "$pattern" || true)
|
||||
if [ -n "$MATCHES" ]; then
|
||||
echo -e "${RED} ✗ Found temporary test files matching '$pattern':${NC}"
|
||||
echo "$MATCHES" | sed 's/^/ - /'
|
||||
((ERRORS++))
|
||||
TEMP_TESTS_FOUND=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $TEMP_TESTS_FOUND -eq 0 ]; then
|
||||
echo -e "${GREEN} ✓ No temporary test files found${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 4: Large Files
|
||||
echo -e "${BLUE}[4/8] Checking for large files (>1MB)...${NC}"
|
||||
|
||||
LARGE_FILES=$(git ls-files | while read file; do
|
||||
if [ -f "$file" ]; then
|
||||
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)
|
||||
if [ "$size" -gt 1048576 ]; then
|
||||
echo "$file ($(numfmt --to=iec-i --suffix=B $size 2>/dev/null || echo "$((size / 1024))KB"))"
|
||||
fi
|
||||
fi
|
||||
done)
|
||||
|
||||
if [ -n "$LARGE_FILES" ]; then
|
||||
echo -e "${YELLOW} ⚠ Found large files:${NC}"
|
||||
echo "$LARGE_FILES" | sed 's/^/ - /'
|
||||
echo -e "${YELLOW} → Ensure these are necessary for the PR${NC}"
|
||||
((WARNINGS++))
|
||||
else
|
||||
echo -e "${GREEN} ✓ No large files found${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 5: Potential Secrets
|
||||
echo -e "${BLUE}[5/8] Checking for potential secrets...${NC}"
|
||||
|
||||
SECRET_PATTERNS=(
|
||||
"\.env$"
|
||||
"\.env\.local$"
|
||||
"credentials\.json$"
|
||||
"\.key$"
|
||||
"\.pem$"
|
||||
"secret"
|
||||
"password"
|
||||
"api[_-]?key"
|
||||
"access[_-]?token"
|
||||
)
|
||||
|
||||
SECRETS_FOUND=0
|
||||
for pattern in "${SECRET_PATTERNS[@]}"; do
|
||||
MATCHES=$(git ls-files | grep -iE "$pattern" || true)
|
||||
if [ -n "$MATCHES" ]; then
|
||||
echo -e "${RED} ✗ Found potential secrets matching '$pattern':${NC}"
|
||||
echo "$MATCHES" | sed 's/^/ - /'
|
||||
((ERRORS++))
|
||||
SECRETS_FOUND=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $SECRETS_FOUND -eq 0 ]; then
|
||||
echo -e "${GREEN} ✓ No potential secrets found in file names${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 6: PR Size
|
||||
echo -e "${BLUE}[6/8] Checking PR size...${NC}"
|
||||
|
||||
# Get default branch (usually main or master)
|
||||
DEFAULT_BRANCH=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5)
|
||||
if [ -z "$DEFAULT_BRANCH" ]; then
|
||||
DEFAULT_BRANCH="main"
|
||||
fi
|
||||
|
||||
# Count lines changed
|
||||
if git rev-parse --verify "origin/$DEFAULT_BRANCH" > /dev/null 2>&1; then
|
||||
LINES_CHANGED=$(git diff --shortstat "origin/$DEFAULT_BRANCH" | grep -oE '[0-9]+ insertion|[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc || echo "0")
|
||||
FILES_CHANGED=$(git diff --name-only "origin/$DEFAULT_BRANCH" | wc -l)
|
||||
|
||||
echo -e "${BLUE} Lines changed:${NC} $LINES_CHANGED"
|
||||
echo -e "${BLUE} Files changed:${NC} $FILES_CHANGED"
|
||||
|
||||
if [ "$LINES_CHANGED" -lt 50 ]; then
|
||||
echo -e "${GREEN} ✓ Small PR (< 50 lines) - Ideal!${NC}"
|
||||
elif [ "$LINES_CHANGED" -lt 200 ]; then
|
||||
echo -e "${GREEN} ✓ Good PR size (< 200 lines)${NC}"
|
||||
elif [ "$LINES_CHANGED" -lt 400 ]; then
|
||||
echo -e "${YELLOW} ⚠ Large PR (< 400 lines) - Consider splitting if possible${NC}"
|
||||
((WARNINGS++))
|
||||
else
|
||||
echo -e "${RED} ✗ Very large PR (>= 400 lines) - Strongly consider splitting${NC}"
|
||||
((ERRORS++))
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW} ⚠ Cannot compare with origin/$DEFAULT_BRANCH${NC}"
|
||||
((WARNINGS++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 7: Uncommitted Changes
|
||||
echo -e "${BLUE}[7/8] Checking for uncommitted changes...${NC}"
|
||||
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
echo -e "${YELLOW} ⚠ You have uncommitted changes${NC}"
|
||||
git status --short | sed 's/^/ /'
|
||||
echo -e "${YELLOW} → Commit or stash these before creating PR${NC}"
|
||||
((WARNINGS++))
|
||||
else
|
||||
echo -e "${GREEN} ✓ No uncommitted changes${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check 8: Branch Name
|
||||
echo -e "${BLUE}[8/8] Checking branch name...${NC}"
|
||||
|
||||
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
|
||||
echo -e "${RED} ✗ You're on $CURRENT_BRANCH branch!${NC}"
|
||||
echo -e "${RED} → Never create PRs from main/master${NC}"
|
||||
echo -e "${RED} → Create a feature branch instead${NC}"
|
||||
((ERRORS++))
|
||||
else
|
||||
echo -e "${GREEN} ✓ On feature branch: $CURRENT_BRANCH${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
echo -e "${BLUE} Summary${NC}"
|
||||
echo -e "${BLUE}====================================${NC}"
|
||||
|
||||
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ All checks passed!${NC}"
|
||||
echo -e "${GREEN}Your branch is ready for PR submission.${NC}"
|
||||
exit 0
|
||||
elif [ $ERRORS -eq 0 ]; then
|
||||
echo -e "${YELLOW}⚠ $WARNINGS warning(s) found${NC}"
|
||||
echo -e "${YELLOW}Review warnings above and address if needed.${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}✗ $ERRORS error(s) found${NC}"
|
||||
if [ $WARNINGS -gt 0 ]; then
|
||||
echo -e "${YELLOW}⚠ $WARNINGS warning(s) found${NC}"
|
||||
fi
|
||||
echo -e "${RED}Fix errors above before submitting PR.${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Next steps:${NC}"
|
||||
echo -e " 1. Remove personal artifacts: ${YELLOW}git rm --cached <file>${NC}"
|
||||
echo -e " 2. Clean branch: ${YELLOW}./scripts/clean-branch.sh${NC}"
|
||||
echo -e " 3. Re-run this check: ${YELLOW}./scripts/pre-pr-check.sh${NC}"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user