Skip to content
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
93 changes: 87 additions & 6 deletions .github/workflows/maintainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,79 @@ jobs:
- name: Install caretaker
run: |
VERSION=$(cat .github/maintainer/.version)
pip install "caretaker-github @ git+https://github.com/ianlintner/caretaker.git@v${VERSION}"
pip install "git+https://github.com/ianlintner/caretaker.git@v${VERSION}"
# LiteLLM is the ``llm-multi`` extra from caretaker's
# pyproject.toml; installing it separately keeps the install
# line above compatible with both the pre- and post-v0.8.1
# distribution rename (``caretaker`` vs ``caretaker-github``).
# Harmless when ``executor.foundry.enabled=false`` — no model
# is called — but required when the repo opts into the
# custom coding agent (see docs/custom-coding-agent-plan.md).
pip install "litellm>=1.50,<2"

# Cheap, offline sanity check — runs before every doctor/run call
# so a broken pin, unparseable config, or missing secret for an
# enabled agent fails loudly with an actionable row instead of
# getting swallowed by a later 403 / import error. See the
# 2026-04-22 audio_engineer outage post-mortem.
- name: Caretaker bootstrap-check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Preferred: pass GitHub App credentials so caretaker self-mints
# tokens via GitHubAppCredentialsProvider (auto-refresh, no expiry).
# Set CARETAKER_APP_ID (var) + CARETAKER_APP_PRIVATE_KEY (secret)
# and un-comment these three lines:
# CARETAKER_GITHUB_APP_ID: ${{ vars.CARETAKER_APP_ID }}
# CARETAKER_GITHUB_APP_INSTALLATION_ID: ${{ vars.CARETAKER_APP_INSTALLATION_ID }}
# CARETAKER_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CARETAKER_APP_PRIVATE_KEY }}
COPILOT_PAT: ${{ secrets.COPILOT_PAT }}
# Add your LLM provider credentials here. Examples:
# Azure AI Foundry (recommended):
AZURE_AI_API_KEY: ${{ secrets.AZURE_AI_API_KEY }}
AZURE_AI_API_BASE: ${{ secrets.AZURE_AI_API_BASE }}
# Azure OpenAI (classic):
# AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }}
# AZURE_API_BASE: ${{ secrets.AZURE_API_BASE }}
# Direct Anthropic (if not using Azure AI Foundry):
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# Fleet registry OAuth2 client_credentials wiring (only consumed
# when fleet_registry.enabled=true in config.yml). Safe to leave
# unset otherwise — caretaker just skips the heartbeat.
OAUTH2_CLIENT_ID: ${{ secrets.OAUTH2_CLIENT_ID }}
OAUTH2_CLIENT_SECRET: ${{ secrets.OAUTH2_CLIENT_SECRET }}
OAUTH2_TOKEN_URL: ${{ vars.OAUTH2_TOKEN_URL }}
OAUTH2_SCOPE: ${{ vars.OAUTH2_SCOPE }}
run: |
caretaker doctor \
--config .github/maintainer/config.yml \
--bootstrap-check

- name: Run
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Preferred: GitHub App self-mint credentials (see bootstrap-check above).
# CARETAKER_GITHUB_APP_ID: ${{ vars.CARETAKER_APP_ID }}
# CARETAKER_GITHUB_APP_INSTALLATION_ID: ${{ vars.CARETAKER_APP_INSTALLATION_ID }}
# CARETAKER_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CARETAKER_APP_PRIVATE_KEY }}
# Fine-grained PAT for a real write-capable user or machine user.
# Caretaker uses this for Copilot issue assignment and @copilot comments
# that must not be authored as github-actions[bot].
COPILOT_PAT: ${{ secrets.COPILOT_PAT }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# LLM provider credentials — add whichever your config uses:
AZURE_AI_API_KEY: ${{ secrets.AZURE_AI_API_KEY }}
AZURE_AI_API_BASE: ${{ secrets.AZURE_AI_API_BASE }}
# AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }}
# AZURE_API_BASE: ${{ secrets.AZURE_API_BASE }}
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CARETAKER_EVENT_PAYLOAD: ${{ toJSON(github.event) }}
CARETAKER_RUN_MODE: ${{ github.event.inputs.mode || 'full' }}
CARETAKER_EVENT_TYPE: ${{ github.event_name }}
CARETAKER_FLEET_SECRET: ${{ secrets.CARETAKER_FLEET_SECRET }}
# Fleet registry OAuth2 client_credentials wiring (only consumed when
# fleet_registry.enabled=true in config.yml).
OAUTH2_CLIENT_ID: ${{ secrets.OAUTH2_CLIENT_ID }}
OAUTH2_CLIENT_SECRET: ${{ secrets.OAUTH2_CLIENT_SECRET }}
OAUTH2_TOKEN_URL: ${{ vars.OAUTH2_TOKEN_URL }}
OAUTH2_SCOPE: ${{ vars.OAUTH2_SCOPE }}
run: |
caretaker run \
--config .github/maintainer/config.yml \
Expand All @@ -139,6 +198,8 @@ jobs:
name: caretaker-memory-snapshot-${{ github.run_number }}
path: .caretaker-memory-snapshot.json
if-no-files-found: ignore
# Required: upload-artifact v4 excludes dotfiles by default.
include-hidden-files: true
retention-days: 30

# When the caretaker run itself fails, trigger the self-heal agent
Expand All @@ -158,16 +219,29 @@ jobs:
- name: Install caretaker
run: |
VERSION=$(cat .github/maintainer/.version)
pip install "caretaker-github @ git+https://github.com/ianlintner/caretaker.git@v${VERSION}"
pip install "git+https://github.com/ianlintner/caretaker.git@v${VERSION}"
# LiteLLM is the ``llm-multi`` extra from caretaker's
# pyproject.toml; installing it separately keeps the install
# line above compatible with both the pre- and post-v0.8.1
# distribution rename (``caretaker`` vs ``caretaker-github``).
# Harmless when ``executor.foundry.enabled=false`` — no model
# is called — but required when the repo opts into the
# custom coding agent (see docs/custom-coding-agent-plan.md).
pip install "litellm>=1.50,<2"

- name: Self-heal — analyse own failure
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Preferred: GitHub App self-mint credentials.
# CARETAKER_GITHUB_APP_ID: ${{ vars.CARETAKER_APP_ID }}
# CARETAKER_GITHUB_APP_INSTALLATION_ID: ${{ vars.CARETAKER_APP_INSTALLATION_ID }}
# CARETAKER_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CARETAKER_APP_PRIVATE_KEY }}
# Fine-grained PAT for a real write-capable user or machine user.
COPILOT_PAT: ${{ secrets.COPILOT_PAT }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
AZURE_AI_API_KEY: ${{ secrets.AZURE_AI_API_KEY }}
AZURE_AI_API_BASE: ${{ secrets.AZURE_AI_API_BASE }}
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CARETAKER_FAILED_RUN_ID: ${{ github.run_id }}
CARETAKER_FLEET_SECRET: ${{ secrets.CARETAKER_FLEET_SECRET }}
CARETAKER_EVENT_PAYLOAD: >-
{
"workflow_run": {
Expand All @@ -177,9 +251,16 @@ jobs:
"head_branch": "${{ github.ref_name }}"
}
}
# Fleet registry OAuth2 client_credentials wiring (self-heal also
# emits a heartbeat). Only used when fleet_registry.enabled=true.
OAUTH2_CLIENT_ID: ${{ secrets.OAUTH2_CLIENT_ID }}
OAUTH2_CLIENT_SECRET: ${{ secrets.OAUTH2_CLIENT_SECRET }}
OAUTH2_TOKEN_URL: ${{ vars.OAUTH2_TOKEN_URL }}
OAUTH2_SCOPE: ${{ vars.OAUTH2_SCOPE }}
run: |
caretaker run \
--config .github/maintainer/config.yml \
--mode self-heal \
--event-type workflow_run \
--event-payload "$CARETAKER_EVENT_PAYLOAD"

Loading