-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.yaml.example
More file actions
460 lines (439 loc) · 24.6 KB
/
Copy pathconfig.yaml.example
File metadata and controls
460 lines (439 loc) · 24.6 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
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# RelEasy config.yaml — stable infrastructure for ONE project.
#
# Three files make up a project's on-disk footprint:
#
# 1. config.yaml — this file. Origin, target branch, AI
# settings, notifications, pr_policy. Rarely
# edited once a project is set up.
# 2. <target_branch>.session.yaml
# — per-effort source data: the `features:`
# list and `pr_sources:` selectors. Edit this
# between runs as your target work changes.
# Named after the target branch (falls back to
# <name> when target_branch is unset) and lives
# next to config.yaml by default; point
# elsewhere with `session_file:` below or
# `--session-file` on the CLI.
# 3. <name>.state.yaml — runtime progress. Managed by RelEasy; lives
# in ${XDG_STATE_HOME:-~/.local/state}/releasy/.
#
# `--stateless` (e.g. `releasy refresh --address-review --stateless`) loads
# THIS file (overridable with `--config`) but skips the session and state files.
# ── Project identity (required) ─────────────────────────────────────
# Unique slug for this project on this machine. Doubles as the filename
# of the per-project state file (and the session file when target_branch
# is unset):
# state: ${XDG_STATE_HOME:-~/.local/state}/releasy/<name>.state.yaml
# session: <dir-of-this-config>/<target_branch>.session.yaml
# Allowed characters: A-Z a-z 0-9 . _ - (1-64 chars). Pick something
# stable like the target branch you are porting onto. Renaming this
# orphans the old state file — use `releasy adopt` to rebind state to a
# moved/renamed config.
name: antalya-26.3
# ── Session file (optional override) ────────────────────────────────
# By default the session file lives at
# `<config-dir>/<target_branch>.session.yaml` (falling back to
# `<name>.session.yaml` when target_branch is unset).
# Set this to point somewhere else (absolute or relative to this file's
# directory). The CLI `--session-file <path>` always takes precedence.
# session_file: sessions/antalya-26.3.session.yaml
# ── Push & PR control ───────────────────────────────────────────────
# Push branches to origin and open PRs.
# Default is false — everything stays local until you enable this.
# push: true
# ── Sequential mode ─────────────────────────────────────────────────
# When true, RelEasy processes the merged-time-sorted PR queue one PR
# per `releasy run` / `releasy continue` invocation:
# 1. The first invocation ports the earliest-merged PR, pushes it,
# opens a rebase PR, and exits.
# 2. You review the PR; once CI is green you approve & merge it
# manually into target_branch.
# 3. The next `releasy continue` checks GitHub: if the previous
# rebase PR was merged, it ports the next PR (created from the
# now-updated target_branch). If not yet merged, it exits with a
# non-zero status and changes nothing.
#
# Default: false (batch mode — every discovered PR is ported in one go).
# Incompatible with `pr_sources.groups` in the session file (session
# load will fail).
# sequential: false
# ── Conflict handling ───────────────────────────────────────────────
# When a cherry-pick conflicts and the AI resolver is disabled or gives
# up (after exhausting `ai_resolve.max_iterations` build attempts), the
# pipeline:
# * Singleton PR or first-of-group: aborts the cherry-pick, deletes the
# local port branch (it has no useful commits), records the entry as
# "Conflict" in the GitHub Project. No push, no PR.
# * Group with N>=1 successful prior picks: aborts the failed pick,
# pushes the branch as-is, opens a DRAFT PR labelled
# `ai-needs-attention` with a banner explaining what failed, and
# records "Conflict" in the GitHub Project. Remaining PRs in
# the group are not attempted.
# Either way the pipeline keeps going with the next unit.
# ── Existing-PR behaviour ───────────────────────────────────────────
# When a PR for the port branch already exists on GitHub:
# false (default) — leave it exactly as-is. Don't try to create a new
# one (avoids GitHub 422s) and don't touch its
# title/body/labels. You can still edit the PR
# manually on GitHub.
# true — reuse the same PR but overwrite its title and body
# with what releasy would have set (source-PR refs,
# combined group body, ai-resolved prefix, …). Handy
# when source PR descriptions changed or you tweaked
# the body format and want the rebase PR to reflect
# it.
# update_existing_prs: false
# ── Merged-port label (optional) ────────────────────────────────────
# When set, releasy applies this label to the rebase (port) PR once it
# has been merged into target_branch, and strips the same label from
# every source PR the port was cherry-picked from. Useful for marking
# "this PR has been ported into release X" with a single label that
# moves automatically as ports land.
#
# Source-PR cleanup is best-effort and only touches PRs hosted on the
# configured origin — source PRs on a different repo are skipped (RelEasy
# never writes outside origin). The label is auto-created on origin the
# first time a merged port is observed.
#
# Each tracked unit is processed exactly once: a per-feature flag on
# the state file (`merged_label_applied`) prevents re-hitting GitHub on
# every subsequent `releasy run`. Renaming the label here does NOT
# auto-relabel previously-processed units.
#
# Requires push: true to take effect. Unset / empty disables the feature.
# merged_label: port-antalya
# merged_label_color: "8B5CF6" # 6-hex color used when releasy creates
# # the label on origin (default: purple).
# ── Work directory ──────────────────────────────────────────────────
# Where to clone/find the origin repo for git operations.
# If it points to an existing git repo, it will be reused (no clone).
# If omitted, uses the current working directory.
# Can also be overridden with --work-dir on the CLI.
# work_dir: /path/to/ClickHouse
# ── Session log (optional) ───────────────────────────────────────
# Append a full transcript of the process (stdout and stderr: Rich
# output, ``click`` messages, ``logging`` warnings, tracebacks) to a file
# for post-run analysis. Relative paths resolve against the directory
# that contains this config file.
# log_file: .releasy/releasy.log
# ── Origin (required) ──────────────────────────────────────────────
# The repo you work against. This is the only repo RelEasy tracks
# as a configured remote.
origin:
remote: https://github.com/Altinity/ClickHouse.git
remote_name: origin
# ── Optional upstream remote (AI prerequisite detection only) ───────
# Fetch-only remote the AI resolver may `git log -S <symbol>` against to
# identify which upstream PR introduced a missing foundation. RelEasy
# NEVER pushes here and never reads code from it for resolution — only
# commit references. Auto-added to the local clone on demand.
# upstream:
# remote: https://github.com/ClickHouse/ClickHouse.git
# remote_name: upstream
# branch: master
# ── Project & target branch ────────────────────────────────────────
# Short project identifier — used to name port branches as
# feature/<base>/<feature-id>
project: antalya
# The base/target branch PRs are opened into. Two ways to set it:
#
# 1. Explicit (recommended): set 'target_branch' here. --onto becomes
# optional and you don't need a tag-based name derivation.
#
# 2. Derived: leave 'target_branch' unset and pass --onto <ref> on
# the CLI. The base branch is then '<project>-<version>', where
# <version> is parsed from --onto (e.g. v26.3.4.234-lts → 26.3,
# yielding 'antalya-26.3').
#
# The base branch must already exist on origin before running.
target_branch: antalya-26.3
# ── PR policy ──────────────────────────────────────────────────────
# Policy knobs that apply to EVERY discovered unit (by_labels entries,
# explicit include_prs, groups, …). These live here — not in the
# session file — because they're stable infrastructure: what to do
# with branches, when to retry, whether to open PRs. Edit the session
# file to change *what* to port; edit pr_policy to change *how*.
#
# All values shown below are defaults; omit pr_policy entirely to
# accept them all.
#
# pr_policy:
# if_exists: skip
# # When the port branch already exists locally AND no rebase PR has
# # been opened for it yet:
# # "skip" (default) — leave the local branch alone; don't re-process.
# # Also: refuse to start if a cherry-pick / merge
# # / rebase is still in progress in the work dir.
# # "recreate" — delete the local branch and rebuild from base.
# # Also: if a cherry-pick / merge / rebase is in
# # progress at startup, abort it and start fresh.
# # "append" — cherry-pick any declared PRs that aren't on the
# # existing branch onto its tip and update the
# # rebase PR body to match the declared group
# # order. Use when you've added a PR to a group
# # that already shipped through a prior run and
# # you want to top up the existing branch / PR
# # rather than rebuild from scratch.
# # Detection uses the ``Source-PR:`` commit
# # trailers releasy writes; falls back to ``skip``
# # with a warning if the existing commits don't
# # match a prefix of the declared group.
# # Mostly for groups (singletons have one PR, so
# # there's nothing to top up). The remote-already-
# # exists safety lock is bypassed in this mode
# # since appending is the explicit user opt-in.
# #
# # ONCE A REBASE PR IS OPEN: if_exists no longer controls whether the
# # branch is rebuilt — it never is. `releasy run` switches to
# # merging origin/<base> into the PR branch (the same flow
# # `releasy refresh` uses): clean merge → leave PR alone, conflict →
# # AI-resolve and plain push. Pass --merge-target on the CLI to
# # push a fresh merge commit even on clean merges. The only setting
# # that still touches an open PR's branch directly is `append`,
# # which cherry-picks newly declared PRs on top.
# #
# # Note: if the branch already exists on the REMOTE without a tracked
# # rebase PR, it is ALWAYS skipped in "skip"/"recreate" modes (resolve
# # those manually so you don't clobber someone else's work).
# # Individual session entries (pr_sources.by_labels[] /
# # pr_sources.groups[]) can override this default per-entry with
# # their own if_exists.
# auto_pr: true
# # When true (the default), every pushed port branch gets a PR opened
# # against the base. Set to false to push branches only and open PRs
# # manually. Requires push: true to have any effect.
# retry_failed: true
# # When a PR unit has a `conflict` entry in state from a previous run:
# # true (default) — process the unit again on this run, per the
# # unit's `if_exists` value (see above). For units
# # WITHOUT an open rebase PR, retry can rebuild
# # from base (`recreate`), append, or skip per
# # if_exists. For units WITH an open rebase PR,
# # retry routes through merge-target instead —
# # an open PR's history is never blown away.
# # false — leave the conflicted entry exactly as-is; no
# # cherry-pick, no PR side-effects.
# # CLI flag `--retry-failed / --no-retry-failed` overrides per-invocation.
# recreate_closed_prs: false
# # When true, if state has a rebase_pr_url and that GitHub PR is closed
# # (not merged), allocate `<canonical>-1`, `-2`, … for the port branch
# # name and cherry-pick + open a fresh PR. Off by default: a closed
# # rebase PR just leaves the branch skipped on subsequent runs.
# detect_superseded: true
# # When true (default), the refresh / run sweeps scan the target
# # branch's recent git history AND open PRs targeting the same base
# # for `(cherry picked from commit <sha>)` footers citing any of our
# # tracked entries' source PRs. Matches mark the local entry as
# # `status: superseded` — no further cherry-pick attempts, no
# # monitoring. Disable to keep the old behaviour (releasy keeps
# # refreshing its own port regardless of parallel work).
# ── PR sources and features ─────────────────────────────────────────
# These live in the session file, not here. Look for
# `<target_branch>.session.yaml` next to this config (or wherever `session_file:`
# above points). The session file is where you edit:
#
# * `features:` — the static list of feature branches to rebase.
# * `pr_sources:` — label-based discovery, explicit include/exclude,
# author filters, groups, etc.
#
# See the bundled session template for the full reference.
# ── GitHub Project board ────────────────────────────────────────────
# Sync branch status to a GitHub Project v2 board (optional).
# Only active when push: true.
#
# One-time setup:
# 1. Create a GitHub Project (or run: releasy setup-project)
# 2. Copy the project URL below
# 3. Ensure RELEASY_GITHUB_TOKEN has repo + project scopes
#
# Or auto-setup (creates project + Status field):
# releasy setup-project
#
# Each rebase gets its own view (tab) in the project, named after
# the base branch (e.g. antalya-26.3). Cards are managed automatically.
notifications:
github_project: https://github.com/orgs/Altinity/projects/1
# ── AI conflict resolver (Claude) ───────────────────────────────────
# Optional. When enabled, releasy invokes `claude` to resolve cherry-
# pick conflicts, build, and commit. If Claude prints UNRESOLVED or
# BUILD FAILED (after exhausting `max_iterations` build attempts) or
# fails outright, releasy treats the unit as "Conflict" — see
# the "Conflict handling" section above.
#
# ai_resolve:
# enabled: false
# command: claude
# prompt_file: prompts/resolve_conflict.md
# # Prompt template used by `releasy refresh` when Claude has to
# # drive a `git merge` to completion (keeping an open rebase PR
# # current with its target branch). Same placeholder vocabulary as
# # prompt_file; the difference is the in-progress operation
# # (merge vs cherry-pick) and how to conclude it.
# merge_prompt_file: prompts/resolve_merge_conflict.md
# # Record the conflict and its resolution as TWO commits (raw
# # conflict state, then the fix) for clearer history, using a
# # dedicated prompt. Set false for a single squashed resolution.
# split_conflict_commit: true
# split_prompt_file: prompts/resolve_conflict_split.md
# # Hard cap (passed into the prompt) on how many build attempts
# # Claude is allowed to make per conflict before giving up.
# max_iterations: 5
# timeout_seconds: 7200
# build_command: cd build && ninja
# # Label automatically applied to PRs whose conflicts Claude
# # resolved cleanly.
# label: ai-resolved
# label_color: "8B5CF6"
# # Label applied to DRAFT PRs released by partial-group failures
# # (singleton failures don't get a PR — the local branch is dropped).
# needs_attention_label: ai-needs-attention
# needs_attention_label_color: "D93F0B"
# # How many times to re-invoke Claude when the Anthropic streaming
# # API drops the turn with a transient error (idle timeout, overload,
# # connection reset, …). Each retry is a fresh turn — independent of
# # `max_iterations`.
# api_retries: 3
# api_retry_backoff_seconds: 15
# # When a conflict is identified as a MISSING PREREQUISITE (an
# # upstream PR the target lacks), optionally pull that prerequisite
# # PR in automatically before retrying. Accepts a bool (sugar) or
# # the mapping below. max_prereq_depth caps the recursive dive.
# auto_add_prerequisite_prs:
# enabled: false
# max_prereq_depth: 7
# # Post-resolve verifier: a read-only second AI pass auditing the
# # resolution. Findings → `verify_label` + PR comment. Never rolls
# # back. Roughly doubles AI cost on conflicted PRs.
# verify_resolution: false
# verify_prompt_file: prompts/verify_resolution.md
# verify_timeout_seconds: 1800 # read-only, no build
# verify_label: ai-needs-verify
# verify_label_color: "FBCA04"
# ── AI changelog entry synthesis (Claude) ────────────────────────────
# Optional. When enabled, multi-PR groups get a single user-facing
# CHANGELOG entry composed by Claude based on the constituent PRs'
# titles + bodies. Singletons (one PR per port branch) ALWAYS reuse
# the source PR's `Changelog entry` verbatim — Claude is never invoked
# in that case, so the singleton flow has zero API cost.
#
# The synthesizer is told to:
# - drop intermediate fix-ups inside the group (B fixes a bug A
# introduced earlier in the same group → the user never saw the
# bug, so it doesn't belong in the changelog),
# - drop refactors / internal cleanup with no user-visible effect,
# - keep the entry to one or two terse, imperative-present-tense
# sentences matching typical CHANGELOG.md tone.
#
# Failures are non-fatal: the per-PR fallback (first-PR-in-group's own
# changelog entry) is used and a warning is logged.
#
# ai_changelog:
# enabled: false
# command: claude
# prompt_file: prompts/synthesize_changelog.md
# timeout_seconds: 300
# # Per-PR body trimmed to this many characters before being inlined
# # into the prompt (keeps payloads bounded for chatty source PRs).
# max_pr_body_chars: 3000
# ─────────────────────────────────────────────────────────────────────
# REVIEW RESPONSE (`releasy refresh --address-review`)
#
# Reads review comments left on a PR and lets the AI make code
# changes addressing the feedback. Triggered by `refresh
# --address-review`. Off by default because it spends Anthropic tokens
# and writes to your PR branch.
#
# Trust gate: comments are filtered to "trusted authors" BEFORE the AI
# sees them — untrusted commenters cannot smuggle instructions into the
# run. Two additive sources:
#
# * `trusted_associations` (default OWNER, MEMBER, COLLABORATOR,
# CONTRIBUTOR) — GitHub's per-comment `author_association` field,
# set server-side when the comment is posted. Anyone with a real
# relationship to the repo (owner, org member, explicit
# collaborator, or a prior code contributor) passes automatically.
# Tighten or widen as you like.
# * `trusted_reviewers` — extra logins to trust regardless of their
# association (e.g. an external reviewer you want to whitelist).
#
# Both empty → the run refuses (no trust signal at all).
#
# Linear history is a hard rule: the AI only appends commits (it uses
# `git revert` to retract anything, never amend / rebase / reset).
# RelEasy pushes with plain `git push` at the end.
#
# review_response:
# trusted_associations:
# - OWNER
# - MEMBER
# - COLLABORATOR
# - CONTRIBUTOR
# trusted_reviewers:
# - alice
# - bob
# # Reply in-thread (with a bot footer) on every comment classified as
# # non-actionable. Set to false for a silent run that only reports
# # via the AI's terminal narration.
# reply_to_non_addressable: true
# # Optional: post one extra top-level summary comment on the PR
# # describing what was done (distinct from per-comment replies).
# post_summary_comment: false
# # Advanced overrides — the defaults below are already sensible.
# # command: claude
# # prompt_file: prompts/address_review.md
# # max_iterations: 15
# # timeout_seconds: 7200
# ─────────────────────────────────────────────────────────────────────
# DEPENDENCY GRAPH (`releasy graph discover` / `graph update`)
#
# All optional; defaults are sensible.
# graph:
# # author_association values whose comments graph update feeds to Claude
# # (GitHub-set, unforgeable). Tighten to ["MEMBER"] for org-only.
# trusted_associations: [OWNER, MEMBER, COLLABORATOR]
# # Extra trusted GitHub logins, additive.
# trusted_reviewers: [alice]
# issue_labels: [releasy] # + the target-branch name; created if missing
# post_comment: true # summary comment after each update
# apply_exclusions: true # enforce vetoes via exclude_prs
# minimize_addressed_comments: true # collapse addressed comments as Outdated
# # command: claude
# # prompt_file: prompts/adjust_graph.md
# # timeout_seconds: 7200
# ─────────────────────────────────────────────────────────────────────
# WORKFLOW
#
# The base branch must already exist on origin. The pipeline then ports
# each discovered PR / feature onto it:
#
# releasy run --onto v26.3.4.234-lts # (or just: releasy run, when
# # target_branch is set above)
# → creates "feature/antalya-26.3/<id>" for each PR / feature
# → opens PRs into antalya-26.3 (if push + pr_policy.auto_pr)
#
# On unresolved conflict:
# * Singleton / first-of-group: nothing local survives — the entry is
# marked "Conflict" in the GitHub Project. Resolve manually
# in the source PR and re-run releasy.
# * Partial group: a draft PR is opened, labelled `ai-needs-attention`.
# Fix the conflict on that branch, push, mark the PR ready.
#
# The pipeline never stalls on a single bad unit anymore — it just
# flags it and moves on.
#
# Once a batch of rebase PRs is open, the target branch keeps moving as
# other work lands. Some PRs will eventually conflict with the new tip:
#
# releasy refresh
# → strictly maintenance: never opens new PRs, never creates new
# branches, never discovers new sources. Only refreshes entries
# already in the per-project state file.
# → for each tracked PR with a branch + rebase PR URL:
# fetch latest tips, attempt `git merge --no-ff origin/<base>`
# into the PR branch. Clean merge: leave the PR alone. Conflict
# + AI resolves: push the resolved merge commit. Conflict + AI
# gives up: abort the merge, reset, mark the entry "Conflict".
# → uses `ai_resolve.merge_prompt_file` (same machinery as cherry-pick
# resolution; different in-progress operation and prompt framing).
# → exits 1 if any PR ended up in conflict — suitable for cron / CI.
# ─────────────────────────────────────────────────────────────────────