Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions .github/workflows/self-healing.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: "\U0001F527 Self-Healing"
name: 🔧 Self-Healing

on:
schedule:
- cron: '0 6 * * *' # Daily at 6 AM UTC
workflow_dispatch:
workflow_run:
workflows: ["\U0001F680 Auto Deploy"]
workflows: ["🚀 Auto Deploy"]
types: [completed]

permissions:
Expand All @@ -27,7 +27,6 @@ jobs:
run: |
if [ -z "$DEPLOY_URL" ]; then
echo "::notice::DEPLOY_URL secret is not configured. Skipping health check."
echo "::notice::To enable monitoring, add a DEPLOY_URL secret pointing to your deployment (e.g. https://your-app.example.com)"
echo "status=skip" >> $GITHUB_OUTPUT
else
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$DEPLOY_URL/api/health" --max-time 30 || echo "000")
Expand All @@ -46,19 +45,10 @@ jobs:
run: |
echo "::error::Health check failed (Status: ${{ steps.health.outputs.status }})"
echo "Triggering rollback..."
gh workflow run auto-deploy.yml --ref $(git rev-parse HEAD~1)
gh workflow run auto-deploy.yml --ref $(git rev-parse HEAD~1) || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not swallow rollback dispatch failures

When the health check is non-200, this step is the only place that can fail the monitor job and trigger Create Issue on Failure (if: failure()). Appending || true masks real rollback-trigger errors (for example, invalid ref, missing workflow, or GitHub API/auth failures), so the workflow can report success even though rollback never started and no incident issue is created.

Useful? React with 👍 / 👎.

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh workflow run ... || true makes the Auto-Rollback step always succeed. Since the subsequent issue creation is gated by if: failure(), a rollback trigger failure will no longer surface via an issue (and the monitor job will almost never be marked failed). Consider removing || true, or explicitly capturing the gh exit code and failing the step (or switching the issue step condition to steps.health.outputs.status != '200' && steps.health.outputs.status != 'skip').

Suggested change
gh workflow run auto-deploy.yml --ref $(git rev-parse HEAD~1) || true
gh workflow run auto-deploy.yml --ref $(git rev-parse HEAD~1)

Copilot uses AI. Check for mistakes.
env:
GH_TOKEN: ${{ github.token }}
Comment on lines 46 to 50

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previously existing "Attempt Auto-Fix" step was removed. The PR description focuses on fixing non-fast-forward dependency-update pushes, so this is an additional behavior change in the self-healing flow. If this removal is intentional, please reflect it in the PR description; otherwise consider restoring the step.

Copilot uses AI. Check for mistakes.

- name: Attempt Auto-Fix
if: steps.health.outputs.status != '200' && steps.health.outputs.status != 'skip'
run: |
echo "Attempting automatic fixes..."
if [ -f "package.json" ]; then
npm ci || true
npm run build || true
fi

- name: Create Issue on Failure
if: failure()
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
Expand All @@ -68,7 +58,7 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Self-Healing: Deployment Health Check Failed',
body: `Deployment health check failed.\n\nStatus: ${{ steps.health.outputs.status }}\nWorkflow: ${context.workflow}\nRun: ${context.runId}`,
body: `Deployment health check failed.\n\nWorkflow: ${context.workflow}\nRun: ${context.runId}`,

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue body no longer includes the health-check HTTP status, which makes triage harder (especially when the endpoint returns a non-200 but the workflow otherwise succeeds). Consider adding the recorded ${{ steps.health.outputs.status }} back into the issue body (or include the failing URL / response metadata).

Suggested change
body: `Deployment health check failed.\n\nWorkflow: ${context.workflow}\nRun: ${context.runId}`,
body: `Deployment health check failed.\n\nWorkflow: ${context.workflow}\nRun: ${context.runId}\nStatus: ${{ steps.health.outputs.status }}`,

Copilot uses AI. Check for mistakes.
labels: ['bug', 'deployment', 'auto-generated']
})

Expand Down Expand Up @@ -96,16 +86,21 @@ jobs:
BRANCH="chore/auto-update-deps-$(date +%Y%m%d)"
git config user.name "BlackRoad Bot"
git config user.email "bot@blackroad.io"
# Delete remote branch if it exists from a prior run
git push origin --delete "$BRANCH" 2>/dev/null || true
git checkout -b "$BRANCH"
git add package*.json
git commit -m "chore: auto-update npm dependencies $(date +%Y-%m-%d)"
git push origin "$BRANCH"
Comment on lines +89 to 94

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unconditionally deleting the remote branch can disrupt any existing open PR that uses this head ref (it temporarily deletes the PR branch and rewrites its commit history on re-push). A safer approach is to keep the branch and push with --force-with-lease when necessary, or only delete the branch when there is no open PR for it.

Suggested change
# Delete remote branch if it exists from a prior run
git push origin --delete "$BRANCH" 2>/dev/null || true
git checkout -b "$BRANCH"
git add package*.json
git commit -m "chore: auto-update npm dependencies $(date +%Y-%m-%d)"
git push origin "$BRANCH"
# Create or reset local branch for this run without deleting any existing remote branch
git checkout -B "$BRANCH"
git add package*.json
git commit -m "chore: auto-update npm dependencies $(date +%Y-%m-%d)"
git push --force-with-lease origin "$BRANCH"

Copilot uses AI. Check for mistakes.
gh pr create \
--title "chore: auto-update npm dependencies $(date +%Y-%m-%d)" \
--body "Automated dependency update created by the self-healing workflow.\n\nPlease review the changes and merge if CI passes." \
--base main \
--head "$BRANCH" \
--label "dependencies"
# Create PR only if it doesn't exist already
gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' | grep -q '^[0-9]' && \
echo "::notice::PR already exists for branch $BRANCH" || \
gh pr create \
--title "chore: auto-update npm dependencies $(date +%Y-%m-%d)" \
--body "Automated dependency update created by the self-healing workflow." \
--base main \
--head "$BRANCH" \
--label "dependencies" || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Let dependency PR creation failures fail loudly

The dependency update path now suppresses all gh pr create failures, so auth/permission/rate-limit/API errors will be silently ignored and the job still succeeds. In runs where dependencies changed, this can leave the automation effectively broken (no PR opened) without any signal to operators, which makes stale dependencies harder to detect and fix.

Useful? React with 👍 / 👎.

Comment on lines +96 to +103

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final || true on gh pr create will mask failures to create the PR (auth issues, API errors, branch protection, etc.), making the workflow appear successful even though the dependency update wasn't surfaced for review. Consider handling the failure explicitly (e.g., emit an ::error:: and fail the step/job, or create an issue/notice path) so the automation remains observable.

Suggested change
gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' | grep -q '^[0-9]' && \
echo "::notice::PR already exists for branch $BRANCH" || \
gh pr create \
--title "chore: auto-update npm dependencies $(date +%Y-%m-%d)" \
--body "Automated dependency update created by the self-healing workflow." \
--base main \
--head "$BRANCH" \
--label "dependencies" || true
if gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' | grep -q '^[0-9]'; then
echo "::notice::PR already exists for branch $BRANCH"
else
if ! gh pr create \
--title "chore: auto-update npm dependencies $(date +%Y-%m-%d)" \
--body "Automated dependency update created by the self-healing workflow." \
--base main \
--head "$BRANCH" \
--label "dependencies"; then
echo "::error::Failed to create PR for branch $BRANCH"
exit 1
fi
fi

Copilot uses AI. Check for mistakes.
else
echo "::notice::All dependencies are up to date. No PR needed."
fi
Expand Down
Loading