diff --git a/.github/BOT_PR_TEMPLATE.md b/.github/BOT_PR_TEMPLATE.md new file mode 100644 index 0000000..9081532 --- /dev/null +++ b/.github/BOT_PR_TEMPLATE.md @@ -0,0 +1,28 @@ + + +## 🤖 Automated Dependency Update + +### Summary + + +### Changes + + +### Upstream References + + +### Impact Assessment +- [ ] Breaking changes: **None** / **Documented below** +- [ ] Security fixes: **None** / **Documented below** +- [ ] Requires manual testing: **No** / **Yes - see below** + +### Testing + + +### Tracking +- Weekly batch: `YYYY-MM-DD` +- Issue reference: `#` or `n/a` (tracked in weekly log) + +--- +*This PR was automatically generated by the Praxis bot update workflow.* +*For questions or to report issues, please tag @plures/maintainers.* diff --git a/.github/bot-logs/INDEX.md b/.github/bot-logs/INDEX.md new file mode 100644 index 0000000..b786c63 --- /dev/null +++ b/.github/bot-logs/INDEX.md @@ -0,0 +1,32 @@ +# Bot Activity Logs Index + +This directory contains weekly logs of automated bot activities in the Praxis repository. +Each log captures dependency updates, version bumps, and other automated maintenance tasks. + +## Purpose +- Track bot activities even when no GitHub issue is created +- Provide audit trail for automated changes +- Enable review of batch updates over time +- Reduce PR/commit churn by batching weekly updates + +## How It Works + +1. **Weekly Schedule**: Automated logs are generated every Monday at 10:00 UTC +2. **Batch Updates**: Dependabot and other bot updates are grouped and reviewed weekly +3. **Audit Trail**: Each weekly log includes: + - Summary of all bot PRs merged that week + - Links to upstream changes and release notes + - Impact assessment (breaking changes, security fixes) + - Testing status + +## Configuration + +Bot update behavior is controlled by: +- `.github/dependabot.yml` - Dependency update grouping and scheduling +- `.github/workflows/bot-weekly-log.yml` - Weekly activity logging +- `.github/BOT_PR_TEMPLATE.md` - Standard PR format for bot updates + +## Weekly Logs + + +*No logs yet. The first log will be generated on the next Monday after this file is committed.* diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2feb294..55a6904 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,22 +5,64 @@ updates: directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + day: "monday" + time: "09:00" # UTC timezone + open-pull-requests-limit: 5 + groups: + npm-production: + patterns: + - "*" + exclude-patterns: + - "@types/*" + - "@vitest/*" + - "typescript" + - "tsup" + - "vite" + - "vitest" + update-types: + - "minor" + - "patch" + npm-dev-tools: + patterns: + - "@types/*" + - "@vitest/*" + - "typescript" + - "tsup" + - "vite" + - "vitest" + update-types: + - "minor" + - "patch" labels: - "dependencies" - "npm" + - "bot-update" commit-message: - prefix: "chore" + prefix: "chore(deps)" include: "scope" + pull-request-branch-name: + separator: "/" # Enable version updates for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" + day: "monday" + time: "09:00" # UTC timezone + groups: + github-actions: + patterns: + - "*" + update-types: + - "minor" + - "patch" labels: - "dependencies" - "github-actions" + - "bot-update" commit-message: - prefix: "chore" + prefix: "chore(deps)" include: "scope" + pull-request-branch-name: + separator: "/" diff --git a/.github/workflows/batch-pin-bumps.yml b/.github/workflows/batch-pin-bumps.yml new file mode 100644 index 0000000..8a88e7c --- /dev/null +++ b/.github/workflows/batch-pin-bumps.yml @@ -0,0 +1,173 @@ +name: Batch Pin Bumps (Weekly) + +on: + schedule: + # Run every Monday at 08:00 UTC (before the weekly log) + - cron: "0 8 * * 1" + workflow_dispatch: + inputs: + force_update: + description: 'Force update even if no changes detected' + required: false + default: 'false' + +permissions: + contents: write + pull-requests: write + +jobs: + batch-pin-updates: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Get week label + id: week + run: | + WEEK_LABEL=$(date -u +%Y-W%U) + BRANCH_NAME="bot/weekly-pins-$WEEK_LABEL" + echo "label=$WEEK_LABEL" >> $GITHUB_OUTPUT + echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: Check for pin updates + id: check + run: | + # This is a placeholder for custom pin update logic + # Projects can customize this step to check their specific pin files + # Examples: package-lock.json, pnpm-lock.yaml, flake.lock, etc. + + CHANGES_DETECTED=false + SUMMARY="" + + # Check for pnpm lockfile updates + if [ -f "pnpm-lock.yaml" ]; then + # Run pnpm update to check for available updates + if command -v pnpm &> /dev/null; then + pnpm install + if git diff --quiet pnpm-lock.yaml; then + echo "No pnpm lockfile changes detected" + else + CHANGES_DETECTED=true + SUMMARY="${SUMMARY}\n- Updated pnpm lockfile" + fi + fi + fi + + # Check for package-lock.json updates + if [ -f "package-lock.json" ]; then + if command -v npm &> /dev/null; then + npm install + if git diff --quiet package-lock.json; then + echo "No npm lockfile changes detected" + else + CHANGES_DETECTED=true + SUMMARY="${SUMMARY}\n- Updated npm lockfile" + fi + fi + fi + + echo "changes=$CHANGES_DETECTED" >> $GITHUB_OUTPUT + echo "summary<> $GITHUB_OUTPUT + echo -e "$SUMMARY" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Create PR if changes detected + if: steps.check.outputs.changes == 'true' || github.event.inputs.force_update == 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + BRANCH="${{ steps.week.outputs.branch }}" + WEEK="${{ steps.week.outputs.label }}" + + # Configure git + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Create and switch to new branch + git checkout -b "$BRANCH" + + # Add all changes + git add -A + + # Commit with descriptive message + COMMIT_TITLE="chore: weekly pin bumps for $WEEK" + COMMIT_BODY="Automated weekly dependency pin updates. + + This PR batches all pin updates for the week to reduce commit churn. + Review the lockfile changes for any unexpected updates. + + Tracking: Weekly log $WEEK" + + git commit -m "$COMMIT_TITLE" -m "$COMMIT_BODY" + + # Push branch + git push origin "$BRANCH" + + # Get template content + TEMPLATE_FILE=".github/BOT_PR_TEMPLATE.md" + + # Create PR body + PR_BODY="## 🤖 Automated Weekly Pin Updates + + **Week:** $WEEK + **Type:** Dependency lockfile updates + + ### Summary + This PR batches all dependency pin bumps for the week to reduce commit churn and improve reviewability. + + ### Changes + ${{ steps.check.outputs.summary }} + + ### Upstream References + - Review the lockfile diff for specific package version changes + - Check individual package changelogs for breaking changes + + ### Impact Assessment + - [ ] Breaking changes: **Review lockfile diff** + - [ ] Security fixes: **Check dependency security advisories** + - [ ] Requires manual testing: **Yes - verify builds and tests pass** + + ### Testing + \`\`\`bash + npm run build + npm run test + npm run typecheck + \`\`\` + + ### Tracking + - Weekly batch: $WEEK + - Issue reference: n/a (tracked in weekly bot log) + + --- + *This PR was automatically generated by the batch-pin-bumps workflow.* + *For questions or to report issues, please tag @plures/maintainers.*" + + # Create PR + gh pr create \ + --title "chore(deps): weekly pin bumps - $WEEK" \ + --body "$PR_BODY" \ + --base main \ + --head "$BRANCH" \ + --label "dependencies,bot-update,automated-pins" + + - name: Report status + run: | + echo "## 🤖 Pin Bump Check Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Week:** ${{ steps.week.outputs.label }}" >> $GITHUB_STEP_SUMMARY + echo "**Changes detected:** ${{ steps.check.outputs.changes }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${{ steps.check.outputs.changes }}" == "true" ]; then + echo "A PR has been created with the weekly pin updates." >> $GITHUB_STEP_SUMMARY + else + echo "No pin updates needed this week." >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/bot-weekly-log.yml b/.github/workflows/bot-weekly-log.yml new file mode 100644 index 0000000..7b2f104 --- /dev/null +++ b/.github/workflows/bot-weekly-log.yml @@ -0,0 +1,158 @@ +name: Weekly Bot Activity Log + +on: + schedule: + # Run every Monday at 10:00 UTC + - cron: "0 10 * * 1" + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + issues: read + +jobs: + log-weekly-activity: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Get date range for last week + id: dates + run: | + END_DATE=$(date -u +%Y-%m-%d) + START_DATE=$(date -u -d '7 days ago' +%Y-%m-%d) + WEEK_LABEL=$(date -u -d '7 days ago' +%Y-W%U) + echo "start=$START_DATE" >> $GITHUB_OUTPUT + echo "end=$END_DATE" >> $GITHUB_OUTPUT + echo "week=$WEEK_LABEL" >> $GITHUB_OUTPUT + + - name: Collect bot activity + id: activity + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + START_DATE: ${{ steps.dates.outputs.start }} + END_DATE: ${{ steps.dates.outputs.end }} + run: | + # Get bot PRs merged in the last week + BOT_PRS=$(gh pr list \ + --state merged \ + --label bot-update \ + --search "merged:>=$START_DATE" \ + --json number,title,mergedAt,url \ + --limit 100) + + # Get dependabot PRs merged in the last week + DEPENDABOT_PRS=$(gh pr list \ + --state merged \ + --author "dependabot[bot]" \ + --search "merged:>=$START_DATE" \ + --json number,title,mergedAt,url \ + --limit 100) + + # Count activities + BOT_COUNT=$(echo "$BOT_PRS" | jq '. | length') + DEPENDABOT_COUNT=$(echo "$DEPENDABOT_PRS" | jq '. | length') + + echo "bot_count=$BOT_COUNT" >> $GITHUB_OUTPUT + echo "dependabot_count=$DEPENDABOT_COUNT" >> $GITHUB_OUTPUT + + # Create weekly summary + mkdir -p .github/bot-logs + LOG_FILE=".github/bot-logs/${{ steps.dates.outputs.week }}.md" + + cat > "$LOG_FILE" <> "$LOG_FILE" + else + echo "- No bot-managed PRs merged this week" >> "$LOG_FILE" + fi + + cat >> "$LOG_FILE" <> "$LOG_FILE" + else + echo "- No dependabot PRs merged this week" >> "$LOG_FILE" + fi + + echo "log_file=$LOG_FILE" >> $GITHUB_OUTPUT + + - name: Update index + run: | + mkdir -p .github/bot-logs + INDEX_FILE=".github/bot-logs/INDEX.md" + + cat > "$INDEX_FILE" <> "$INDEX_FILE" + done + + - name: Commit and push logs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + git add .github/bot-logs/ + + if git diff --staged --quiet; then + echo "No changes to commit" + else + # Note: This commits directly to main for audit logging purposes. + # Ensure branch protection rules allow github-actions[bot] to push. + git commit -m "chore: update bot activity log for week ${{ steps.dates.outputs.week }}" + git push origin HEAD:main + fi + + - name: Create summary + run: | + echo "## 🤖 Weekly Bot Activity Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Week:** ${{ steps.dates.outputs.week }}" >> $GITHUB_STEP_SUMMARY + echo "**Period:** ${{ steps.dates.outputs.start }} to ${{ steps.dates.outputs.end }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- Bot-managed PRs: ${{ steps.activity.outputs.bot_count }}" >> $GITHUB_STEP_SUMMARY + echo "- Dependabot PRs: ${{ steps.activity.outputs.dependabot_count }}" >> $GITHUB_STEP_SUMMARY + echo "- Total updates: $((${{ steps.activity.outputs.bot_count }} + ${{ steps.activity.outputs.dependabot_count }}))" >> $GITHUB_STEP_SUMMARY diff --git a/README.md b/README.md index 0127b5f..090f795 100644 --- a/README.md +++ b/README.md @@ -1156,6 +1156,8 @@ MIT License - see [LICENSE](./LICENSE) for details. Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) to get started. +**Automated Updates**: This repository uses batched bot updates to reduce commit churn. Dependency updates are grouped weekly and include audit trails. See the [Bot Update Policy](./docs/BOT_UPDATE_POLICY.md) for details. + **Dogfooding Plures Tools**: We actively dogfood all Plures tools during development. If you encounter friction while using any tool, please file a [Dogfooding Friction Report](https://github.com/plures/praxis/issues/new/choose). See the [Dogfooding Quick Start](./docs/DOGFOODING_QUICK_START.md) for details. - 🐛 [Report a bug](https://github.com/plures/praxis/issues/new?template=bug_report.yml) diff --git a/docs/BOT_UPDATE_POLICY.md b/docs/BOT_UPDATE_POLICY.md new file mode 100644 index 0000000..dbd9223 --- /dev/null +++ b/docs/BOT_UPDATE_POLICY.md @@ -0,0 +1,125 @@ +# Bot Update Policy + +## Overview + +This document describes how automated updates (dependency bumps, pin updates, etc.) are managed in the Praxis repository to reduce commit churn and improve reviewability. + +## Goals + +1. **Batch Updates**: Group related updates together instead of creating many small PRs +2. **Improve Auditability**: Require summaries and upstream links for all bot PRs +3. **Maintain Tracking**: Keep audit trail even without dedicated GitHub issues +4. **Reduce Noise**: Weekly batching instead of continuous small updates + +## How It Works + +### Dependabot Configuration + +Dependabot is configured to: +- Run weekly on Mondays at 09:00 UTC +- Group updates by ecosystem (npm production, npm dev, github-actions) +- Limit to 5 open PRs at a time +- Use consistent labels: `dependencies`, `bot-update` +- Follow standardized commit message format: `chore(deps): ...` + +See `.github/dependabot.yml` for full configuration. + +### Weekly Pin Bumps + +The `batch-pin-bumps.yml` workflow: +- Runs every Monday at 08:00 UTC (before dependabot) +- Checks for lockfile updates (pnpm-lock.yaml, package-lock.json) +- Creates a single PR with all pin bumps for the week +- Uses the standard bot PR template for consistency + +### Weekly Activity Log + +The `bot-weekly-log.yml` workflow: +- Runs every Monday at 10:00 UTC (after updates run) +- Collects all bot PRs merged in the past week +- Creates a weekly activity log in `.github/bot-logs/` +- Provides audit trail without requiring GitHub issues +- Commits log directly to main branch + +### PR Template + +All bot PRs use `.github/BOT_PR_TEMPLATE.md` which requires: +- Brief summary of changes +- List of updated dependencies/files +- Links to upstream changelogs or release notes +- Impact assessment (breaking changes, security, testing) +- Weekly batch identifier for tracking + +## For Repository Maintainers + +### Reviewing Bot PRs + +When reviewing automated PRs: + +1. **Check the Summary**: Understand what's being updated +2. **Review Upstream Links**: Look for breaking changes or security fixes +3. **Verify CI Passes**: Ensure all tests and checks pass +4. **Check Impact Assessment**: Pay attention to flagged items +5. **Merge Weekly Batches**: Approve and merge to reduce backlog + +### Customizing Pin Updates + +To add custom pin update checks in `batch-pin-bumps.yml`: + +1. Edit the "Check for pin updates" step +2. Add logic to detect your specific pin files +3. Update the summary to describe what changed +4. Test with workflow_dispatch before scheduling + +### Adjusting Schedule + +To change update frequency: + +1. Edit cron schedules in workflow files +2. Update dependabot.yml schedule.interval +3. Coordinate timing (pin bumps → dependabot → weekly log) + +## For Other Repositories + +This bot update approach can be adopted by other repositories in the Plures organization: + +### Setup Steps + +1. Copy `.github/dependabot.yml` and adjust for your ecosystem +2. Copy `.github/BOT_PR_TEMPLATE.md` +3. Copy `.github/workflows/bot-weekly-log.yml` +4. (Optional) Copy `.github/workflows/batch-pin-bumps.yml` and customize +5. Create `.github/bot-logs/` directory structure +6. Update your README to reference the new bot policy + +### Target Repositories + +As mentioned in the original issue, these repos should adopt this approach: +- ✅ plures/praxis (this repo) +- ⬜ plures/nix-openclaw (issues disabled; track here) +- ⬜ plures/praxis-business +- ⬜ plures/behavior-ledger-github-cicd + +## References + +- Original Issue: Practice: reduce bot churn (batch pin bumps; prefer PRs; add audit trail) +- Dependabot Documentation: https://docs.github.com/en/code-security/dependabot +- GitHub Actions Workflow Syntax: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +## FAQ + +### Why weekly instead of daily? + +Weekly batching significantly reduces PR volume while still keeping dependencies reasonably up-to-date. Security updates can still be handled immediately through manual intervention. + +### What if I need an urgent update? + +You can always create a manual PR for urgent updates. The weekly batching is for routine maintenance only. + +### Where do I find the weekly logs? + +All weekly logs are stored in `.github/bot-logs/` with an index at `.github/bot-logs/INDEX.md`. + +### Can I trigger updates manually? + +Yes! All workflows support `workflow_dispatch` for manual triggering via the GitHub Actions UI. diff --git a/docs/TESTING_BOT_WORKFLOWS.md b/docs/TESTING_BOT_WORKFLOWS.md new file mode 100644 index 0000000..b0f80a7 --- /dev/null +++ b/docs/TESTING_BOT_WORKFLOWS.md @@ -0,0 +1,154 @@ +# Testing Bot Update Workflows + +This guide explains how to test the new batched bot update workflows. + +## Prerequisites + +- GitHub CLI (`gh`) installed and authenticated +- Appropriate repository permissions (write access) + +## Testing Individual Workflows + +### 1. Test Weekly Activity Log + +```bash +# Trigger manually via GitHub Actions UI +# Go to: Actions → Weekly Bot Activity Log → Run workflow + +# Or via GitHub CLI: +gh workflow run bot-weekly-log.yml + +# Check the run: +gh run list --workflow=bot-weekly-log.yml + +# View the output: +gh run view --log +``` + +**Expected Result:** +- A new markdown file created in `.github/bot-logs/` with format `YYYY-Wxx.md` +- The INDEX.md file updated with a link to the new log +- Commit pushed to main branch with message: `chore: update bot activity log for week YYYY-Wxx` + +### 2. Test Batch Pin Bumps + +```bash +# Trigger manually via GitHub Actions UI with force_update option +# Go to: Actions → Batch Pin Bumps (Weekly) → Run workflow → Set force_update to 'true' + +# Or via GitHub CLI: +gh workflow run batch-pin-bumps.yml -f force_update=true + +# Check the run: +gh run list --workflow=batch-pin-bumps.yml + +# Check for created PR: +gh pr list --label bot-update +``` + +**Expected Result:** +- A new branch created: `bot/weekly-pins-YYYY-Wxx` +- A PR opened with title: `chore(deps): weekly pin bumps - YYYY-Wxx` +- PR uses the BOT_PR_TEMPLATE.md format +- PR labeled with: `dependencies`, `bot-update`, `automated-pins` + +### 3. Test Dependabot Grouping + +Dependabot runs automatically on schedule, but you can verify configuration: + +```bash +# Check dependabot configuration +cat .github/dependabot.yml + +# View existing dependabot PRs +gh pr list --author "dependabot[bot]" + +# Check for grouped PRs (should see fewer, larger PRs) +gh pr list --author "dependabot[bot]" --label dependencies +``` + +**Expected Result:** +- Dependabot creates grouped PRs like: + - "Bump the npm-production group with X updates" + - "Bump the npm-dev-tools group with Y updates" + - "Bump the github-actions group with Z updates" + +## Integration Testing + +### Weekly Workflow Sequence + +The workflows run in this order: +1. **08:00 UTC Monday**: `batch-pin-bumps.yml` (creates PR) +2. **09:00 UTC Monday**: Dependabot runs (creates grouped PRs) +3. **10:00 UTC Monday**: `bot-weekly-log.yml` (logs previous week's activity) + +To test the full sequence: + +1. Manually trigger batch-pin-bumps on a Monday +2. Review and merge the created PR +3. Let dependabot run naturally or configure it to run more frequently for testing +4. Manually trigger bot-weekly-log +5. Check `.github/bot-logs/` for the generated log + +## Validation Checklist + +After implementing the bot update approach, verify: + +- [ ] Dependabot creates grouped PRs (not individual dependency PRs) +- [ ] Bot PRs use the standard template format +- [ ] Weekly logs are generated in `.github/bot-logs/` +- [ ] INDEX.md is updated automatically +- [ ] All bot PRs have `bot-update` label +- [ ] Commit messages follow pattern: `chore(deps): ...` +- [ ] No direct commits to main (all updates via PR) + +## Troubleshooting + +### Workflow Fails with Permission Error + +Ensure the workflow has appropriate permissions in `.github/workflows/*.yml`: +```yaml +permissions: + contents: write + pull-requests: write +``` + +### Bot Logs Not Committing + +Check that: +- Git user is configured in the workflow +- GITHUB_TOKEN has write access to the repository +- Branch protection rules allow bot commits + +### No PRs Created + +Verify: +- Changes were actually detected (check step output) +- Branch doesn't already exist +- PR limit not reached (dependabot config: open-pull-requests-limit) + +### Dependabot Not Grouping + +Ensure: +- Using Dependabot v2 configuration format +- `groups:` section is properly configured +- Updates match the group patterns + +## Manual Rollback + +If you need to revert the bot update approach: + +1. Restore original `.github/dependabot.yml` +2. Disable or delete the new workflows: + - `.github/workflows/bot-weekly-log.yml` + - `.github/workflows/batch-pin-bumps.yml` +3. Remove `.github/bot-logs/` directory +4. Remove `.github/BOT_PR_TEMPLATE.md` + +## Next Steps + +Once testing is complete: +1. Monitor for one full week to ensure all workflows run correctly +2. Review the generated logs for completeness +3. Adjust schedules or grouping as needed +4. Share the approach with other Plures repositories