From ed07fef51127f4f7e1cabc421e2a080cde310620 Mon Sep 17 00:00:00 2001 From: Ian Lintner <500914+ianlintner@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:16:19 -0500 Subject: [PATCH] feat(workflow): switch to streaming caretaker backend (v0.23.0) --- .github/workflows/maintainer.yml | 305 +++++++------------------------ 1 file changed, 66 insertions(+), 239 deletions(-) diff --git a/.github/workflows/maintainer.yml b/.github/workflows/maintainer.yml index b40dc8d..c723112 100644 --- a/.github/workflows/maintainer.yml +++ b/.github/workflows/maintainer.yml @@ -1,266 +1,93 @@ -name: Caretaker +# ────────────────────────────────────────────────────────────────────────────── +# Caretaker — thin streaming workflow +# Copy to .github/workflows/maintainer.yml in your repository. +# Generated by: caretaker init-workflow +# Docs: https://github.com/ianlintner/caretaker +# ────────────────────────────────────────────────────────────────────────────── +# +# This workflow does NOT run caretaker on the runner. It mints an OIDC +# token, asks the caretaker backend to execute the run on its own +# infrastructure, and tails the resulting log stream so the GitHub Actions +# log shows live output. Bug fixes ship in the backend without consumer +# repos updating their workflow YAML. +# +# REQUIREMENTS +# ──────────── +# - The caretaker GitHub App must be installed on this repository. +# - The backend at $CARETAKER_BACKEND_URL must be reachable from the runner. +# - No PAT, no LLM keys, no checkout — the backend holds those. +# +# AUTHENTICATION +# ────────────── +# The runner mints a short-lived JWT via GitHub Actions OIDC. The backend +# validates it against GitHub's JWKS, verifies the audience, and +# (optionally) confirms the caretaker App is installed on this repo +# before accepting the run. + +name: Caretaker Maintainer on: schedule: - - cron: "0 8 * * *" - pull_request: - types: [opened, synchronize, reopened] - pull_request_review: - types: [submitted] - check_suite: - types: [completed] - issues: - types: [opened, labeled] - issue_comment: - types: [created] + # Run every 15 minutes (adjust to taste; minimum practical is 5 min). + # The backend deduplicates concurrent runs per repo via the OIDC + # natural key (repository_id, run_id, run_attempt). + - cron: "*/15 * * * *" + workflow_dispatch: inputs: mode: - description: "Run mode" + description: "Run mode (full | pr-only | issue-only | upgrade | security | deps | stale)" required: false default: "full" - type: choice - options: [full, pr-only, issue-only, upgrade, dry-run] -# Prevent concurrent caretaker runs so each run sees the up-to-date memory -# store written by the previous run. + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + + issues: + types: + - opened + - labeled + - reopened + concurrency: - group: caretaker + # Serialise runs on the same ref so the backend doesn't fan out + # redundant agent work. + group: caretaker-${{ github.ref }} cancel-in-progress: false permissions: - contents: write - issues: write - pull-requests: write + id-token: write # mint GitHub Actions OIDC JWT for backend auth + contents: read # the runner doesn't write — the backend does jobs: - # Short-circuit comment events that caretaker itself produced. Without this - # filter, every status / readiness / task comment caretaker writes triggers - # another caretaker run via the issue_comment webhook, producing a feedback - # loop. Comments are identified by a caretaker:* HTML-comment marker and - # by known bot logins. - dispatch-guard: - runs-on: ubuntu-latest - outputs: - should_run: ${{ steps.guard.outputs.should_run }} - steps: - - id: guard - uses: actions/github-script@v7 - with: - script: | - const ev = context.eventName; - if (ev !== "issue_comment" && ev !== "pull_request_review") { - core.setOutput("should_run", "true"); - return; - } - const payload = context.payload || {}; - if (ev === "issue_comment") { - const body = payload.comment?.body || ""; - if (/