forked from makenotion/notion-mcp-server
-
Notifications
You must be signed in to change notification settings - Fork 0
[Self-Heal] Add self-scheduling auto-repair workflow #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
badMade
wants to merge
1
commit into
main
Choose a base branch
from
selfheal-workflow-11919046782672604664
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| schedule: '0 0 * * 0' | ||
| rationale: 'Low velocity (<=5 commits/week) -> runs weekly' | ||
| last_updated: 1780793191727 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| name: Compute Self-Heal Schedule | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: "0 0 * * 0" # Runs weekly to evaluate if schedule needs to be updated | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: compute-schedule-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| actions: read | ||
|
|
||
| jobs: | ||
| compute-schedule: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| steps: | ||
| - name: Check out repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
|
|
||
| - name: Install JS-YAML | ||
| run: npm ci | ||
|
|
||
| - name: Check for recent Open Schedule PRs | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| RECENT_PR=$(gh pr list --label self-heal-schedule --state open --json createdAt -q '.[0].createdAt') | ||
| if [ ! -z "$RECENT_PR" ] && [ "$RECENT_PR" != "null" ]; then | ||
| echo "Open selfheal schedule PR exists. Skipping to avoid thrash." | ||
| exit 0 | ||
| fi | ||
|
|
||
| - name: Setup Git Identity | ||
| run: | | ||
| git config --global user.name "github-actions[bot]" | ||
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| - name: Compute New Schedule | ||
| run: | | ||
| node scripts/compute_schedule.mjs | ||
|
|
||
| - name: Create Schedule Update PR | ||
| if: success() | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| for path in .github/workflows/self-heal.yml .github/self-heal-schedule.yml; do | ||
| git add "$path" 2>/dev/null || true | ||
| done | ||
|
|
||
| if git diff --cached --quiet; then | ||
| echo "Schedule unchanged, no PR needed." | ||
| exit 0 | ||
| fi | ||
|
|
||
| BRANCH_NAME="selfheal-schedule-$(date +%s)" | ||
| git checkout -b "$BRANCH_NAME" | ||
| git commit -m "chore: update self-heal schedule based on telemetry" | ||
| git push origin "$BRANCH_NAME" | ||
|
|
||
| PR_TITLE="[Self-Heal Schedule] Update cadence" | ||
| PR_BODY="Automated self-heal schedule update based on recent commit telemetry." | ||
|
|
||
| gh pr create --title "$PR_TITLE" --body "$PR_BODY" --label "automation,self-heal-schedule" --head "$BRANCH_NAME" --base main |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| name: Self-Heal Repair | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: "0 0 * * 0" # AUTO-UPDATED | ||
| workflow_run: | ||
| workflows: ["ci"] | ||
| types: | ||
| - completed | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: selfheal-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| actions: read | ||
|
|
||
| jobs: | ||
| repair: | ||
| # Trigger gate: run if scheduled, manual, or if CI failed | ||
| if: >- | ||
| (github.event_name == 'schedule') || | ||
| (github.event_name == 'workflow_dispatch') || | ||
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure') | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| steps: | ||
| - name: Check out repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
|
|
||
| - name: Loop Prevention Guard | ||
| run: | | ||
| if [[ "${{ github.ref_name }}" == selfheal-* ]]; then | ||
| echo "Skipping self-heal run on a self-heal branch." | ||
| exit 0 | ||
| fi | ||
|
|
||
| - name: Close stale Self-Heal PRs | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| STALE_DATE=$(date -d "7 days ago" -I) | ||
| gh pr list --label self-heal --search "created:<$STALE_DATE" --json number --jq '.[].number' | xargs -I {} gh pr close {} --comment "Closing stale self-heal PR." || true | ||
|
|
||
| - name: Check for recent Open Self-Heal PRs | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| RECENT_PR=$(gh pr list --label self-heal --state open --json createdAt -q '.[0].createdAt') | ||
| if [ ! -z "$RECENT_PR" ] && [ "$RECENT_PR" != "null" ]; then | ||
| echo "Open selfheal PR exists. Skipping to avoid duplicates." | ||
| exit 0 | ||
| fi | ||
|
|
||
| - name: Setup Git Identity | ||
| run: | | ||
| git config --global user.name "github-actions[bot]" | ||
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| - name: Pre-Healthcheck | ||
| id: pre_healthcheck | ||
| run: | | ||
| node scripts/healthcheck.mjs > pre-check.log 2>&1 || true | ||
|
|
||
| - name: Run Self-Heal Pipeline | ||
| id: repair | ||
| run: | | ||
| node scripts/self_heal.mjs > repair.log 2>&1 | ||
| # Explicitly do NOT use || true here. A failure means no fix or healthcheck failure. | ||
|
|
||
| - name: Post-Healthcheck | ||
| id: post_healthcheck | ||
| if: always() | ||
| run: | | ||
| node scripts/healthcheck.mjs > post-check.log 2>&1 || true | ||
|
|
||
| - name: Upload Logs | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: self-heal-logs | ||
| path: | | ||
| pre-check.log | ||
| repair.log | ||
| post-check.log | ||
|
|
||
| - name: Stage Allowed Files | ||
| if: success() | ||
| run: | | ||
| for path in src/ tests/ package.json package-lock.json eslint.config.mjs; do | ||
| git add "$path" 2>/dev/null || true | ||
| done | ||
| # Ensure generated logs are not staged | ||
| git reset HEAD pre-check.log repair.log post-check.log 2>/dev/null || true | ||
|
|
||
| - name: Check for Entropy Patterns (Secrets) | ||
| if: success() | ||
| run: | | ||
| # Simple check to avoid committing high entropy strings | ||
| if git diff --cached | grep -iE 'api[_-]?key|token|secret|password'; then | ||
| echo "Detected potential secrets in diff. Aborting." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Create Self-Heal PR | ||
| if: success() | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| if git diff --cached --quiet; then | ||
| echo "No changes to commit." | ||
| exit 0 | ||
| fi | ||
|
|
||
| BRANCH_NAME="selfheal-$(date +%s)" | ||
| git checkout -b "$BRANCH_NAME" | ||
| git commit -m "chore: automated self-heal repair" | ||
| git push origin "$BRANCH_NAME" | ||
|
|
||
| if [ "${{ github.event_name }}" == "schedule" ]; then | ||
| PR_TITLE="[Self-Heal Scheduled] Drift fixes" | ||
| elif [ "${{ github.event_name }}" == "workflow_run" ]; then | ||
| PR_TITLE="[Self-Heal Reactive] CI fix" | ||
| else | ||
| PR_TITLE="[Self-Heal Manual] Repair" | ||
| fi | ||
|
|
||
| PR_BODY="Automated self-heal repair generated by Jules/Claude Code. | ||
| Check the uploaded artifacts for detailed pre-check, repair, and post-check logs. | ||
|
|
||
| Trigger: ${{ github.event_name }} | ||
|
|
||
| Review the changes carefully. The pipeline guarantees healthchecks pass after these repairs." | ||
|
|
||
| gh pr create --title "$PR_TITLE" --body "$PR_BODY" --label "automation,self-heal" --head "$BRANCH_NAME" --base main |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Self-Heal Coding Agent Setup | ||
|
|
||
| This repository is configured with a self-adapting, self-healing automated repair pipeline. | ||
|
|
||
| ## Overview | ||
|
|
||
| The setup includes: | ||
| - **Scripts:** Idempotent, deterministic repair actions (`scripts/self_heal.mjs`), a holistic test via (`scripts/healthcheck.mjs`), and a dynamic scheduler (`scripts/compute_schedule.mjs`). | ||
| - **Workflows:** GitHub Actions configured in `.github/workflows/self-heal.yml` to trigger the repair pipeline, and `.github/workflows/compute-schedule.yml` to adjust its frequency. | ||
| - **Config:** `.github/self-heal-schedule.yml` persists the current schedule metadata. | ||
|
|
||
| ## The Repair Pipeline | ||
| When triggered, `scripts/self_heal.mjs` applies repairs in this exact order: | ||
| 1. Rebuild / reinstall (`npm install`) | ||
| 2. Lint / format auto-fix (`eslint --fix` & `prettier --write`) | ||
| 3. Snapshot updates (`vitest run -u`) | ||
| 4. Type stubs acquisition (`typesync`) | ||
| 5. Dependency re-resolve (`npm update`) | ||
| 6. Static asset regeneration (`npm run build`) | ||
|
|
||
| After *each* step, a healthcheck (`scripts/healthcheck.mjs`) is run. If it passes and an actual diff was produced, the process exits successfully, generating a PR for your review. If no repairs were required, no PR is made. | ||
|
|
||
| ## Self-Scheduling | ||
|
|
||
| The system analyzes this project's git commit velocity to automatically adjust the self-healing frequency. | ||
|
|
||
| - **High Activity:** Evaluates multiple times a day. | ||
| - **Dormant:** Evaluates once a week. | ||
|
|
||
| This schedule is managed by the `Compute Self-Heal Schedule` workflow, preventing unnecessary runs in low-activity periods and ensuring high responsiveness during active development. | ||
|
|
||
| ## Triggers | ||
|
|
||
| 1. **Scheduled (Proactive):** The computed schedule defined in `.github/workflows/self-heal.yml` triggers routine drift checks. | ||
| 2. **Reactive:** Automatically attempts repair if the main `ci` workflow fails. | ||
| 3. **Manual Dispatch:** Can be manually started from the Actions tab. | ||
|
|
||
| ## Reviewer Checklist | ||
|
|
||
| When reviewing a PR generated by this bot (`[Self-Heal Scheduled]...` or `[Self-Heal Reactive]...`), verify that: | ||
| - [ ] You have inspected the Pre-check and Post-check artifacts linked in the PR. | ||
| - [ ] No regressions or unexpected logic changes have occurred (as the bot restricts itself to formatters, dependency updates, and snapshots). | ||
| - [ ] The generated fix aligns with project intent. | ||
|
|
||
| ## Overriding the Schedule | ||
| To override the automatically computed schedule: | ||
| 1. Update `.github/self-heal-schedule.yml` with your desired `schedule` cron expression and `rationale`. | ||
| 2. Push your changes. The `compute_schedule.mjs` script will honor this modification until enough time/telemetry passes to naturally adapt again. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import eslint from '@eslint/js'; | ||
| import tseslint from 'typescript-eslint'; | ||
| import globals from 'globals'; | ||
|
|
||
| export default tseslint.config( | ||
| { | ||
| ignores: ['build/**', 'dist/**', 'coverage/**', 'bin/**', 'node_modules/**'] | ||
| }, | ||
| eslint.configs.recommended, | ||
| ...tseslint.configs.recommended, | ||
| { | ||
| languageOptions: { | ||
| globals: { | ||
| ...globals.node, | ||
| ...globals.browser, | ||
| ...globals.jest, | ||
| ...globals.vitest | ||
| } | ||
| }, | ||
| rules: { | ||
| '@typescript-eslint/no-explicit-any': 'warn', | ||
| '@typescript-eslint/ban-ts-comment': 'warn', | ||
| '@typescript-eslint/no-unused-vars': 'warn', | ||
| 'prefer-const': 'warn', | ||
| 'preserve-caught-error': 'warn' | ||
| } | ||
| } | ||
| ); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rule
preserve-caught-erroris not a valid core ESLint rule. Configuring a non-existent rule without a plugin prefix will cause ESLint to throw a fatal error and fail to run, which will break the healthcheck and self-heal scripts.