Automated Maintenance #18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Automated Maintenance | |
on: | |
schedule: | |
# Run weekly on Sundays at 3 AM UTC | |
- cron: '0 3 * * 0' | |
workflow_dispatch: | |
inputs: | |
force_cleanup: | |
description: 'Force cleanup of old artifacts' | |
required: false | |
default: 'false' | |
type: boolean | |
jobs: | |
# ============================================================================ | |
# REPOSITORY MAINTENANCE | |
# ============================================================================ | |
repo-maintenance: | |
name: Repository Maintenance | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
issues: write | |
actions: write | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Clean up old artifacts | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const owner = context.repo.owner; | |
const repo = context.repo.repo; | |
const forceCleanup = '${{ github.event.inputs.force_cleanup }}' === 'true'; | |
// Keep artifacts for different periods based on type | |
const retentionPolicies = { | |
'release-': 90, // Release artifacts: 90 days | |
'debug-': 14, // Debug builds: 14 days | |
'test-': 7, // Test artifacts: 7 days | |
'security-': 30, // Security analysis: 30 days | |
}; | |
const artifacts = await github.rest.actions.listArtifactsForRepo({ | |
owner, | |
repo, | |
per_page: 100 | |
}); | |
let deletedCount = 0; | |
for (const artifact of artifacts.data.artifacts) { | |
const artifactAge = Date.now() - new Date(artifact.created_at); | |
const ageDays = Math.floor(artifactAge / (1000 * 60 * 60 * 24)); | |
let retentionDays = 30; // default | |
// Determine retention policy based on artifact name | |
for (const [prefix, days] of Object.entries(retentionPolicies)) { | |
if (artifact.name.startsWith(prefix)) { | |
retentionDays = days; | |
break; | |
} | |
} | |
if (ageDays > retentionDays || forceCleanup) { | |
console.log(`Deleting artifact: ${artifact.name} (${ageDays} days old)`); | |
await github.rest.actions.deleteArtifact({ | |
owner, | |
repo, | |
artifact_id: artifact.id | |
}); | |
deletedCount++; | |
} | |
} | |
console.log(`Cleaned up ${deletedCount} old artifacts`); | |
- name: Check repository health | |
run: | | |
echo '🔍 Checking repository health...' | |
# Check repository size | |
REPO_SIZE=$(du -sh .git | cut -f1) | |
echo "Repository size: $REPO_SIZE" | |
# Count files | |
FILE_COUNT=$(find . -type f -not -path './.git/*' | wc -l) | |
echo "File count: $FILE_COUNT" | |
# Check for large files | |
echo "Large files (>1MB):" | |
find . -type f -not -path './.git/*' -size +1M -exec ls -lh {} \; || echo "No large files found" | |
# Check for common issues | |
echo "Checking for common issues..." | |
# Check for DS_Store files | |
if find . -name ".DS_Store" -not -path './.git/*' | grep -q .; then | |
echo "⚠️ Found .DS_Store files - consider adding to .gitignore" | |
fi | |
# Check for backup files | |
if find . -name "*.bak" -o -name "*~" -not -path './.git/*' | grep -q .; then | |
echo "⚠️ Found backup files - consider cleanup" | |
fi | |
echo "✅ Repository health check completed" | |
# ============================================================================ | |
# DEPENDENCY HEALTH CHECK | |
# ============================================================================ | |
dependency-health: | |
name: Dependency Health Check | |
runs-on: macos-14 | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Install Nix | |
uses: DeterminateSystems/nix-installer-action@v17 | |
- name: Setup Nix Cache | |
uses: DeterminateSystems/magic-nix-cache-action@v10 | |
- name: Check Swift dependencies | |
run: | | |
nix develop --command bash -c " | |
echo '📦 Checking Swift dependencies health...' | |
# Show dependency tree | |
swift package show-dependencies --format json > deps.json | |
# Count dependencies | |
DEP_COUNT=\$(jq '.dependencies | length' deps.json) | |
echo \"Total Swift dependencies: \$DEP_COUNT\" | |
# Check for development dependencies | |
if jq -e '.dependencies[] | select(.kind == \"fileSystem\")' deps.json >/dev/null; then | |
echo '⚠️ Local file dependencies detected' | |
fi | |
# Check Package.resolved for version locks | |
if [ -f Package.resolved ]; then | |
RESOLVED_COUNT=\$(jq '.pins | length' Package.resolved) | |
echo \"Resolved packages: \$RESOLVED_COUNT\" | |
fi | |
echo '✅ Swift dependency health check completed' | |
" | |
- name: Check Zig dependencies | |
run: | | |
nix develop --command bash -c " | |
echo '📦 Checking Zig dependencies health...' | |
if [ -f build.zig.zon ]; then | |
echo 'Zig dependencies found:' | |
cat build.zig.zon | |
else | |
echo 'No Zig dependencies file found' | |
fi | |
# Check for any .zig files in deps | |
if [ -d .zigmod ] || [ -d zig-cache ]; then | |
echo 'Zig cache directories found' | |
fi | |
echo '✅ Zig dependency health check completed' | |
" | |
- name: Generate dependency report | |
run: | | |
echo '📋 Generating dependency report...' | |
cat > dependency-report.md << 'EOF' | |
# Dependency Health Report | |
Generated on: $(date) | |
## Swift Dependencies | |
EOF | |
if [ -f deps.json ]; then | |
echo '### Package Dependencies' >> dependency-report.md | |
jq -r '.dependencies[] | "- **\(.identity)**: \(.kind)"' deps.json >> dependency-report.md | |
fi | |
echo '' >> dependency-report.md | |
echo '## Recommendations' >> dependency-report.md | |
echo '- Review dependencies quarterly for updates' >> dependency-report.md | |
echo '- Monitor for security advisories' >> dependency-report.md | |
echo '- Consider dependency count vs. functionality' >> dependency-report.md | |
# ============================================================================ | |
# BUILD PERFORMANCE MONITORING | |
# ============================================================================ | |
build-performance: | |
name: Build Performance Monitoring | |
runs-on: macos-14 | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Install Nix | |
uses: DeterminateSystems/nix-installer-action@v17 | |
- name: Setup Nix Cache | |
uses: DeterminateSystems/magic-nix-cache-action@v10 | |
- name: Measure build performance | |
run: | | |
echo '⏱️ Measuring build performance...' | |
# Clean build test | |
echo 'Testing clean build performance...' | |
time nix develop --command bash -c " | |
zig build swift --summary all | |
" | |
# Incremental build test | |
echo 'Testing incremental build performance...' | |
time nix develop --command bash -c " | |
zig build swift --summary all | |
" | |
# Binary size check | |
BINARY_SIZE=$(stat -f%z .build/release/plue 2>/dev/null || echo "0") | |
echo "Final binary size: $BINARY_SIZE bytes" | |
# Create performance report | |
cat > performance-report.md << EOF | |
# Build Performance Report | |
Generated on: $(date) | |
## Metrics | |
- Binary size: $BINARY_SIZE bytes | |
- Platform: macOS (GitHub Actions) | |
- Build configuration: Release | |
## Notes | |
- Build times measured on GitHub Actions runners | |
- Binary size should be monitored for growth | |
- Consider optimization if size exceeds reasonable limits | |
EOF | |
# ============================================================================ | |
# AUTOMATED ISSUE MANAGEMENT | |
# ============================================================================ | |
issue-management: | |
name: Automated Issue Management | |
runs-on: ubuntu-latest | |
permissions: | |
issues: write | |
steps: | |
- name: Close stale issues | |
uses: actions/stale@v9 | |
with: | |
repo-token: ${{ secrets.GITHUB_TOKEN }} | |
stale-issue-message: | | |
This issue has been automatically marked as stale because it has not had | |
recent activity. It will be closed if no further activity occurs within 7 days. | |
If this issue is still relevant, please: | |
- Add a comment explaining why it should remain open | |
- Add the "keep-open" label | |
- Provide additional context or updates | |
close-issue-message: | | |
This issue has been automatically closed due to inactivity. | |
If you believe this issue should remain open, please: | |
- Reopen the issue | |
- Provide additional context | |
- Add the "keep-open" label to prevent future auto-closure | |
stale-issue-label: 'stale' | |
exempt-issue-labels: 'keep-open,pinned,security,critical' | |
days-before-stale: 60 | |
days-before-close: 7 | |
operations-per-run: 30 | |
- name: Label enhancement requests | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const issues = await github.rest.issues.listForRepo({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'open', | |
per_page: 100 | |
}); | |
for (const issue of issues.data) { | |
if (issue.pull_request) continue; // Skip PRs | |
const body = issue.body?.toLowerCase() || ''; | |
const title = issue.title?.toLowerCase() || ''; | |
// Auto-label based on content | |
const labels = []; | |
if (title.includes('feature') || body.includes('feature request')) { | |
labels.push('enhancement'); | |
} | |
if (title.includes('bug') || body.includes('bug report')) { | |
labels.push('bug'); | |
} | |
if (title.includes('performance') || body.includes('performance')) { | |
labels.push('performance'); | |
} | |
if (title.includes('security') || body.includes('security')) { | |
labels.push('security'); | |
} | |
if (labels.length > 0) { | |
await github.rest.issues.addLabels({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: issue.number, | |
labels: labels | |
}); | |
} | |
} | |
# ============================================================================ | |
# DOCUMENTATION MAINTENANCE | |
# ============================================================================ | |
documentation-check: | |
name: Documentation Check | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Check documentation completeness | |
run: | | |
echo '📚 Checking documentation completeness...' | |
# Check for essential documentation files | |
MISSING_DOCS=() | |
if [ ! -f README.md ]; then | |
MISSING_DOCS+=("README.md") | |
fi | |
if [ ! -f CONTRIBUTING.md ]; then | |
MISSING_DOCS+=("CONTRIBUTING.md") | |
fi | |
if [ ! -f CHANGELOG.md ]; then | |
MISSING_DOCS+=("CHANGELOG.md") | |
fi | |
if [ ! -f LICENSE ] && [ ! -f LICENSE.md ]; then | |
MISSING_DOCS+=("LICENSE") | |
fi | |
if [ ${#MISSING_DOCS[@]} -gt 0 ]; then | |
echo "⚠️ Missing documentation files:" | |
printf '%s\n' "${MISSING_DOCS[@]}" | |
else | |
echo "✅ All essential documentation files present" | |
fi | |
# Check README sections | |
if [ -f README.md ]; then | |
echo "Checking README.md structure..." | |
if ! grep -qi "installation" README.md; then | |
echo "⚠️ README.md missing installation section" | |
fi | |
if ! grep -qi "usage" README.md; then | |
echo "⚠️ README.md missing usage section" | |
fi | |
if ! grep -qi "development" README.md; then | |
echo "⚠️ README.md missing development section" | |
fi | |
fi | |
# ============================================================================ | |
# MAINTENANCE SUMMARY | |
# ============================================================================ | |
maintenance-summary: | |
name: Maintenance Summary | |
runs-on: ubuntu-latest | |
needs: [repo-maintenance, dependency-health, build-performance, documentation-check] | |
if: always() | |
steps: | |
- name: Create maintenance summary | |
run: | | |
echo "## 🔧 Weekly Maintenance Summary" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "**Date**: $(date)" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "### Status Overview" >> $GITHUB_STEP_SUMMARY | |
if [ "${{ needs.repo-maintenance.result }}" = "success" ]; then | |
echo "✅ Repository Maintenance: Completed" >> $GITHUB_STEP_SUMMARY | |
else | |
echo "❌ Repository Maintenance: Issues detected" >> $GITHUB_STEP_SUMMARY | |
fi | |
if [ "${{ needs.dependency-health.result }}" = "success" ]; then | |
echo "✅ Dependency Health: Good" >> $GITHUB_STEP_SUMMARY | |
else | |
echo "❌ Dependency Health: Needs attention" >> $GITHUB_STEP_SUMMARY | |
fi | |
if [ "${{ needs.build-performance.result }}" = "success" ]; then | |
echo "✅ Build Performance: Monitored" >> $GITHUB_STEP_SUMMARY | |
else | |
echo "❌ Build Performance: Issues detected" >> $GITHUB_STEP_SUMMARY | |
fi | |
if [ "${{ needs.documentation-check.result }}" = "success" ]; then | |
echo "✅ Documentation: Up to date" >> $GITHUB_STEP_SUMMARY | |
else | |
echo "❌ Documentation: Needs updates" >> $GITHUB_STEP_SUMMARY | |
fi | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "### Next Actions" >> $GITHUB_STEP_SUMMARY | |
echo "- Review any failed checks above" >> $GITHUB_STEP_SUMMARY | |
echo "- Update dependencies if needed" >> $GITHUB_STEP_SUMMARY | |
echo "- Address documentation gaps" >> $GITHUB_STEP_SUMMARY | |
echo "- Monitor build performance trends" >> $GITHUB_STEP_SUMMARY |