Files
BMAD-METHOD/implement-fork-friendly-ci.sh
Bragatte 052e84dd4a feat: implement fork-friendly CI/CD with opt-in mechanism (#476)
- CI/CD disabled by default in forks to conserve resources
- Users can enable via ENABLE_CI_IN_FORK repository variable
- Added comprehensive Fork Guide documentation
- Updated README with Contributing section
- Created automation script for future implementations

Benefits:
- Saves GitHub Actions minutes across 1,600+ forks
- Cleaner fork experience for contributors
- Full control for fork owners
- PR validation still runs automatically

BREAKING CHANGE: CI/CD no longer runs automatically in forks.
Fork owners must set ENABLE_CI_IN_FORK=true to enable workflows.

Co-authored-by: Brian <bmadcode@gmail.com>
Co-authored-by: PinkyD <paulbeanjr@gmail.com>
2025-08-30 22:15:31 -05:00

229 lines
7.3 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Fork-Friendly CI/CD Implementation Script
# Usage: ./implement-fork-friendly-ci.sh
#
# This script automates the implementation of fork-friendly CI/CD
# by adding fork detection conditions to all GitHub Actions workflows
set -e
echo "🚀 Implementing Fork-Friendly CI/CD..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 1. Check if .github/workflows directory exists
if [ ! -d ".github/workflows" ]; then
echo -e "${RED}${NC} No .github/workflows directory found"
echo "This script must be run from the repository root"
exit 1
fi
# 2. Backup existing workflows
echo "📦 Backing up workflows..."
backup_dir=".github/workflows.backup.$(date +%Y%m%d_%H%M%S)"
cp -r .github/workflows "$backup_dir"
echo -e "${GREEN}${NC} Workflows backed up to $backup_dir"
# 3. Count workflow files and jobs
WORKFLOW_COUNT=$(ls -1 .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null | wc -l)
echo "📊 Found ${WORKFLOW_COUNT} workflow files"
# 4. Process each workflow file
UPDATED_FILES=0
MANUAL_REVIEW_NEEDED=0
for file in .github/workflows/*.yml .github/workflows/*.yaml; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo -n "Processing ${filename}... "
# Create temporary file
temp_file="${file}.tmp"
# Track if file needs manual review
needs_review=0
# Process the file with awk
awk '
BEGIN {
in_jobs = 0
job_count = 0
modified = 0
}
/^jobs:/ {
in_jobs = 1
print
next
}
# Match job definitions (2 spaces + name + colon)
in_jobs && /^ [a-z][a-z0-9_-]*:/ {
job_name = $0
print job_name
job_count++
# Look ahead for existing conditions
getline next_line
# Check if next line is already an if condition
if (next_line ~ /^ if:/) {
# Job already has condition - combine with fork detection
existing_condition = next_line
sub(/^ if: /, "", existing_condition)
# Check if fork condition already exists
if (existing_condition !~ /github\.event\.repository\.fork/) {
print " # Fork-friendly CI: Combined with existing condition"
print " if: (" existing_condition ") && (github.event.repository.fork != true || vars.ENABLE_CI_IN_FORK == '\''true'\'')"
modified++
} else {
# Already has fork detection
print next_line
}
} else if (next_line ~ /^ runs-on:/) {
# No condition exists, add before runs-on
print " if: github.event.repository.fork != true || vars.ENABLE_CI_IN_FORK == '\''true'\''"
print next_line
modified++
} else {
# Some other configuration, preserve as-is
print next_line
}
next
}
# Reset when leaving jobs section
/^[a-z]/ && in_jobs {
in_jobs = 0
}
# Print all other lines
{
if (!in_jobs) print
}
END {
if (modified > 0) {
exit 0 # Success - file was modified
} else {
exit 1 # No modifications needed
}
}
' "$file" > "$temp_file"
# Check if modifications were made
if [ $? -eq 0 ]; then
mv "$temp_file" "$file"
echo -e "${GREEN}${NC} Updated"
((UPDATED_FILES++))
else
rm -f "$temp_file"
echo -e "${YELLOW}${NC} No changes needed"
fi
# Check for complex conditions that might need manual review
if grep -q "needs:" "$file" || grep -q "strategy:" "$file"; then
echo " ⚠️ Complex workflow detected - manual review recommended"
((MANUAL_REVIEW_NEEDED++))
fi
fi
done
echo -e "${GREEN}${NC} Updated ${UPDATED_FILES} workflow files"
# 5. Create Fork Guide if it doesn't exist
if [ ! -f ".github/FORK_GUIDE.md" ]; then
echo "📝 Creating Fork Guide documentation..."
cat > .github/FORK_GUIDE.md << 'EOF'
# Fork Guide - CI/CD Configuration
## CI/CD in Forks
By default, CI/CD workflows are **disabled in forks** to conserve GitHub Actions resources.
### Enabling CI/CD in Your Fork
If you need to run CI/CD workflows in your fork:
1. Navigate to **Settings** → **Secrets and variables** → **Actions** → **Variables**
2. Click **New repository variable**
3. Create variable:
- **Name**: `ENABLE_CI_IN_FORK`
- **Value**: `true`
4. Click **Add variable**
### Disabling CI/CD Again
Either:
- Delete the `ENABLE_CI_IN_FORK` variable, or
- Set its value to `false`
### Alternative Testing Options
- **Local testing**: Run tests locally before pushing
- **Pull Request CI**: Workflows automatically run when you open a PR
- **GitHub Codespaces**: Full development environment
EOF
echo -e "${GREEN}${NC} Fork Guide created"
else
echo " Fork Guide already exists"
fi
# 6. Validate YAML files (if yamllint is available)
if command -v yamllint &> /dev/null; then
echo "🔍 Validating YAML syntax..."
VALIDATION_ERRORS=0
for file in .github/workflows/*.yml .github/workflows/*.yaml; do
if [ -f "$file" ]; then
filename=$(basename "$file")
if yamllint -d relaxed "$file" &>/dev/null; then
echo -e " ${GREEN}${NC} ${filename}"
else
echo -e " ${RED}${NC} ${filename} - YAML validation failed"
((VALIDATION_ERRORS++))
fi
fi
done
if [ $VALIDATION_ERRORS -gt 0 ]; then
echo -e "${YELLOW}${NC} ${VALIDATION_ERRORS} files have YAML errors"
fi
else
echo " yamllint not found - skipping YAML validation"
echo " Install with: pip install yamllint"
fi
# 7. Summary
echo ""
echo "═══════════════════════════════════════"
echo " Fork-Friendly CI/CD Summary"
echo "═══════════════════════════════════════"
echo " 📁 Files updated: ${UPDATED_FILES}"
echo " 📊 Total workflows: ${WORKFLOW_COUNT}"
echo " 📝 Fork Guide: .github/FORK_GUIDE.md"
if [ $MANUAL_REVIEW_NEEDED -gt 0 ]; then
echo " ⚠️ Files needing review: ${MANUAL_REVIEW_NEEDED}"
fi
echo ""
echo "Next steps:"
echo "1. Review the changes: git diff"
echo "2. Test workflows locally (if possible)"
echo "3. Commit changes: git commit -m 'feat: implement fork-friendly CI/CD'"
echo "4. Push and create PR"
echo ""
echo "Remember to update README.md with fork information!"
echo "═══════════════════════════════════════"
# Exit with appropriate code
if [ $UPDATED_FILES -gt 0 ]; then
exit 0
else
echo "No files were updated - workflows may already be fork-friendly"
exit 1
fi