forked from max-sixty/tend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtend.example.yaml
More file actions
366 lines (348 loc) · 12.7 KB
/
Copy pathtend.example.yaml
File metadata and controls
366 lines (348 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# # Configuration
#
# Place at `.config/tend.yaml`. Regenerate workflows after editing:
#
# uvx tend@latest init
#
# Only `bot_name` is required. Everything else has sensible defaults.
#
# Parsed under YAML 1.2 (ruamel.yaml), so `on`, `yes`, `no`, `off` stay
# strings — only `true`/`false` are booleans.
bot_name: my-project-bot
# ## Harness
#
# Which agent runtime to use. Defaults to "claude" (the official `claude`
# binary run headless behind a credential-injecting proxy). "codex" runs
# OpenAI Codex via `codex exec`.
#
# harness: codex
# ## Model
#
# Model to use for all workflows. Valid values depend on the harness:
#
# - harness: claude — opus (default), sonnet, haiku
# - harness: codex — gpt-5.5 (default); any string Codex CLI accepts
#
# model: opus
# ## Effort (codex only)
#
# Reasoning effort for the Codex model. Valid values: low, medium, high,
# xhigh. Empty (default) leaves the choice to the Codex CLI default
# (medium for gpt-5.5).
#
# effort: medium
# ## Protected branches
#
# The default branch is always protected. Additional long-lived branches
# (e.g. release or staging branches) can be listed here. The bot cannot
# merge to any of them without human approval.
#
# protected_branches: ["release", "staging"]
# ## Secrets
#
# Required secrets, by harness — stored in the repo's `tend` GitHub
# Environment (install-tend creates it; a workflow the bot pushes to a
# branch cannot read them there):
#
# | Harness | Required |
# |------------|---------------------------------------------------------------------------|
# | `claude` | `TEND_BOT_TOKEN` + one of `CLAUDE_CODE_OAUTH_TOKEN` or `ANTHROPIC_API_KEY` |
# | `codex` | `TEND_BOT_TOKEN` + `OPENAI_API_KEY` |
#
# `TEND_BOT_TOKEN` is the bot account's PAT (scopes below).
# `CLAUDE_CODE_OAUTH_TOKEN` is from `claude setup-token` (PKCE).
# `ANTHROPIC_API_KEY` is a console.anthropic.com API key.
# `OPENAI_API_KEY` is a standard OpenAI API key. The Codex
# subscription `auth.json` path is not supported — Codex rotates that
# refresh token on every call, so concurrent jobs
# (review/mention/triage/nightly/…) would invalidate each other's auth
# mid-run.
#
# The Claude action prefers the subscription token
# (`CLAUDE_CODE_OAUTH_TOKEN`) over the API key when both are set.
#
# Classic PAT scopes: `repo`, `workflow`, `notifications`, `write:discussion`,
# `gist`, `user`. `workflow` is required to push commits that modify
# `.github/workflows/` files. `gist` lets internal skills store structured
# evidence in secret gists owned by the bot. `user` lets `install-tend` set
# the bot's profile bio so contributors can see the authorization stance.
#
# Fine-grained PAT permissions: `contents:write`, `pull-requests:write`,
# `issues:write`, `actions:write`, `workflows:write`, `discussions:write`,
# `notifications:write`, `gists:write`, plus the account-level `Profile:
# read and write` permission (for the bio). `notifications:write` is
# required so the action can mark threads read after handling an event.
#
# Override names if the repo uses different secret names:
#
# secrets:
# bot_token: MY_BOT_PAT
# claude_token: MY_CLAUDE_TOKEN # claude (OAuth)
# anthropic_api_key: MY_ANTHROPIC_KEY # claude (API key)
# openai_key: MY_OPENAI_KEY # codex
#
# `tend check` flags repo-level secrets not in an explicit allowlist — each
# entry is a deliberate acceptance that any workflow the repo runs can read
# that token. The operational secret names are refused here (a repo-level
# copy of one would reopen what the environment gate closes); a build token
# that belongs at repo level must be listed:
#
# secrets:
# allowed: ["CODECOV_TOKEN", "DEPLOY_KEY"]
# ## Setup steps
#
# Build tools, caches, and environment variables that run before Claude in every
# workflow. A `setup:` entry mirrors a GitHub Actions step: give it exactly
# one of `uses` or `run`, plus any of these optional fields:
#
# name, id, if, with, env, shell, working-directory,
# continue-on-error, timeout-minutes
#
# For multi-step setup, add multiple entries to the `setup:` list — they
# render in declared order. For anything more elaborate (conditional shells,
# shared env across many steps, anchored caches), move the YAML into a local
# composite action (`.github/actions/tend-setup/action.yaml`) and reference
# it from one entry with `uses`.
#
# Setup runs against reviewed code — the default branch, or in `tend-review`
# the PR's base branch, checked out before the PR's own tree lands. Project
# setup that must see the PR's manifests (installing its dependencies) goes in
# `sandbox_setup:` below, which runs inside the Claude harness's sandbox. Under
# codex there is no such lever; the agent installs what it needs itself.
#
# `tend-notifications` injects an `if:` guard on every step so setup is
# skipped when the pre-check finds no work. A user-supplied `if:` is passed
# through unchanged (with a generation-time warning) — your condition wins.
#
# Each form below shows the config and the YAML it produces inside the
# `steps:` block. The `if:` guard injected in `tend-notifications` is shown
# on the first example; it's added the same way on every step.
#
# `uses`:
#
# setup:
# - uses: astral-sh/setup-uv@v6
#
# # renders as (in tend-notifications):
# # - uses: astral-sh/setup-uv@v6
# # if: steps.check.outputs.count != '0' || github.event_name == 'workflow_dispatch'
# #
# # and in other workflows:
# # - uses: astral-sh/setup-uv@v6
#
# `uses` with action inputs and step-level env:
#
# setup:
# - uses: actions/setup-node@v4
# name: Setup Node
# with:
# node-version-file: .node-version
# env:
# FORCE_COLOR: "1"
#
# # renders as:
# # - uses: actions/setup-node@v4
# # name: Setup Node
# # with:
# # node-version-file: .node-version
# # env:
# # FORCE_COLOR: '1'
#
# `run` with shell and working directory:
#
# setup:
# - run: cargo build --release
# shell: bash
# working-directory: ./crates/core
# env:
# RUSTFLAGS: -D warnings
#
# # renders as:
# # - run: cargo build --release
# # shell: bash
# # working-directory: ./crates/core
# # env:
# # RUSTFLAGS: -D warnings
# ## Sandbox setup (Claude harness)
#
# `setup:` above runs as the RUNNER user, around the composite action. The
# `claude` harness runs the agent as a separate, non-sudo sandbox user with a
# fixed env allowlist, so env changes don't carry in, and a PATH entry carries
# in only if the sandbox UID can reach what it points at: a tool in a system
# location (`/opt/hostedtoolcache/...`, where the `setup-*` actions install)
# does, one in the runner's own home does not. Tend installs no language
# toolchain into the sandbox — whatever `setup:` puts somewhere reachable is
# what the agent gets, at the version you pinned. These three keys reach INSIDE
# that sandbox, before the agent launches:
#
# - `sandbox_path`: directories prepended to the sandbox PATH. A leading `~`
# expands to the sandbox home. This is the fix for a toolchain installed in
# the sandbox home but off PATH (e.g. rustup's shims):
#
# sandbox_path:
# - ~/.cargo/bin
#
# - `sandbox_env`: NAME: VALUE pairs added to the agent's launch env. Reserved
# keys (proxy routing, CA trust, dummy credentials, PATH) are rejected — use
# `sandbox_path` for PATH:
#
# sandbox_env:
# RUST_BACKTRACE: "1"
#
# - `sandbox_setup`: shell commands run as the sandbox user after the toolchain
# and plugins install and before the agent runs, with the workspace as cwd.
# The workspace holds the PR's tree by then, so this is where installing the
# project's dependencies belongs (`uv sync`, `npm ci`), alongside other
# on-disk effects like warming a cache. Env-only tweaks don't persist across
# the command's shell — use sandbox_path/sandbox_env:
#
# sandbox_setup:
# - uv sync
#
# The codex harness runs the agent on the runner, so its `setup:` section
# already reaches the agent env; these keys are inert (and warn) under codex.
# ## Workflows
#
# All workflows are enabled by default except ci-fix (requires
# `watched_workflows`). Every workflow accepts these options:
#
# - `enabled` (bool) — disable with `enabled: false`
# - `prompt` (string) — override the default skill invocation
#
# Scheduled workflows also accept `cron` to override their default schedule.
#
# workflows:
# notifications:
# enabled: false
# ### review
#
# Triggers on PR open/update. Reviews for correctness, duplication, error paths.
# Monitors CI. Pushes fixes to bot-authored PRs.
#
# workflows:
# review:
# prompt: "/my-custom-review {pr_number}" # override default prompt
#
# tend-review checks out the prospective post-merge tree
# (`refs/pull/N/merge`) when available, and falls back to the PR branch head
# (`refs/pull/N/head`) when it isn't — GitHub only materializes the merge ref
# for mergeable PRs, so the fallback keeps review running on PRs with merge
# conflicts against the base. On fallback the review sees the PR branch in
# isolation rather than the post-merge tree.
# ### mention
#
# Triggers on @bot mentions and review comments. Responds to requests in PR and
# issue conversations.
# ### triage
#
# Triggers on new issues. Classifies, checks for duplicates, reproduces bugs,
# attempts conservative fixes.
# ### ci-fix
#
# Triggers when a watched CI workflow fails on the default branch. Reads failure
# logs, identifies root cause, opens a fix PR.
#
# workflows:
# ci-fix:
# watched_workflows: ["ci", "build"] # required — names of CI workflows to monitor
# branches: ["main", "v1"] # optional — defaults to default branch only
# ### nightly
#
# Daily (default 06:17 UTC). Resolves conflicts on open PRs, reviews recent
# commits, surveys ~10 files for bugs and stale docs, closes resolved issues,
# regenerates tend workflow files.
#
# workflows:
# nightly:
# cron: "0 8 * * *" # override schedule
# ### weekly
#
# Weekly (default Sunday 09:17 UTC). Reviews dependency PRs, approves safe
# patch and minor updates (a maintainer merges — the bot never merges).
#
# workflows:
# weekly:
# cron: "0 10 * * 1" # override to Monday
# ### notifications
#
# Every 15 minutes. Polls GitHub notifications, responds to unhandled mentions,
# marks handled threads as read.
# ### review-runs
#
# Daily (default 07:47 UTC). Reviews recent CI runs for behavioral problems
# and proposes skill/config improvements.
# ## Workflow overrides
#
# The generator owns every `tend-*.yaml` file — editing them directly loses
# changes on the next `uvx tend@latest init`. To customize the generated YAML,
# set overrides in `.config/tend.yaml`; they survive regeneration.
#
# Two scopes are supported:
#
# - `workflow_extra` — adds or replaces top-level keys (e.g. `env`, `defaults`)
# - `jobs.<name>` — adds or replaces keys inside a specific job
#
# Overrides use RFC 7396 (JSON Merge Patch): mappings deep-merge, scalars and
# lists replace, and `null` deletes the key. Unknown job names print a warning
# but don't fail. Step-level overrides aren't supported — use the `setup:`
# mechanism above to inject steps.
#
# ### Example: skip review on labeled PRs
#
# The `review` job's default `if:` only skips draft PRs. To also skip PRs
# carrying a `tend:dismissed` label (useful once a PR has been reviewed and
# the author doesn't want re-reviews on every push), replace the `if:` —
# scalars replace under JSON Merge Patch, so duplicate the draft check:
#
# workflows:
# review:
# jobs:
# review:
# if: "github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'tend:dismissed')"
#
# ### Example: extend permissions without losing defaults
#
# Mappings deep-merge, so adding one permission preserves the rest:
#
# workflows:
# review:
# jobs:
# review:
# permissions:
# packages: read
#
# ### Example: longer timeout on a specific job
#
# workflows:
# review:
# jobs:
# review:
# timeout-minutes: 240
#
# ### Example: target a specific job in a multi-job workflow
#
# workflows:
# mention:
# jobs:
# handle:
# timeout-minutes: 180
#
# ### Example: top-level env vars
#
# workflows:
# review:
# workflow_extra:
# env:
# MY_VAR: hello
#
# ### Example: delete a generated key with null
#
# YAML has a native `null` literal, so JSON Merge Patch's delete-key
# semantics work directly. Drop the cron schedule from nightly while
# keeping `workflow_dispatch`:
#
# workflows:
# nightly:
# workflow_extra:
# on:
# schedule: null