Skip to content

canary autocut: scope bump signals to watched-path commits, paginate the range, and persist failed promotions #1023

Description

@don-petry

Split out of review feedback on PR #1021 (implements #1019). Both findings are valid and accepted; they are deferred because each needs an interface change, and CodeRabbit itself labelled them 🏗️ Heavy lift. #1021 already fixes the two defects that would have made it a non-fix (compare truncation in _gh_changed_files, and a silent promote-all).

1. _autocut_range_signals — bump signals are unscoped and the range is unpaginated

_autocut_range_signals() {
  local host="$1" base="$2" head="$3" json out
  json="$(gh api "repos/$host/compare/$base...$head" 2>/dev/null)" || return 1
  out="$(jq -r ' … (.commits | map(.commit.message // "")) as $msgs
    | { b: any($msgs[]; test("^\\w+(\\([^)]*\\))?!:") …), f: any($msgs[]; test("^feat…")) } … ')"

Two defects in one function:

  • Unscoped. It scans every commit message in the range. An unrelated docs: feat!: … commit therefore forces a major bump on an otherwise script-only cut. Bump level drives the channel/ring pin surface, so a spurious major seeds a fresh v<newMAJOR>-next (per #657 F4) and consumers pinned to the old major stop receiving updates entirely — a silent-non-delivery outcome, the same class #1019 exists to remove.
  • Unpaginated. Same root cause as the _gh_changed_files truncation bug fixed in #1021: the compare response caps .commits (250) and .files (300) and sets .truncated. Signals beyond the cap are invisible, so a genuine BREAKING CHANGE: in a long range can be missed and ship as a patch — the more dangerous direction.

Why it wasn't fixed in #1021: scoping requires knowing which commits touch a watched path, i.e. per-commit file lists, and the function's (host, base, head) signature carries no agent — so it cannot resolve _watched_paths. That is an interface change plus an API-cost decision (one call per commit), not a local edit.

Acceptance criteria:

  • Bump signals are derived only from commits that touch a watched path for the agent being cut.
  • Truncated ranges are handled explicitly — enumerate commits rather than trusting one capped response.
  • Fail-safe direction is stated and tested: an unresolvable range must not silently downgrade a breaking change to a patch.
  • Tests: unrelated feat! outside watched paths does not raise the bump; a BREAKING CHANGE: in a watched-path commit beyond the compare cap is detected.

2. cmd_promote_all — failed promotions are logged but not persisted

#1021 now emits an aggregated ::warning:: naming every failed agent, so a green sweep no longer looks clean. But the failure is still only in the run log: CANARY_PROMOTIONS_LOG records successful moves only, and sync-issues tracks BLOCKED gate states — not failed tag writes (a permission or API rejection). So a repeatedly-failing tag write leaves no durable artifact and no trend.

Acceptance criteria:

  • Failed promotions are persisted alongside successes (extend CANARY_PROMOTIONS_LOG with an outcome field, or a sibling failure log).
  • A tag write that fails on N consecutive scheduled runs raises or updates a blocker issue, so it escalates like a gate block rather than scrolling past.
  • Distinguish a gate-blocked promotion (expected, already tracked) from a failed tag write (unexpected) — conflating them is what made this invisible.

Context

Found on #1021, whose own history is the argument for both: dev-lead posted detailed replies claiming fixes for the truncation and summary defects — naming functions and citing new bats tests — and made none of them (#1567). The fixes in #1021 are hand-applied steering commits (a700662, 55fe2e8). Please verify these by diffing the head, not by reading a reply.

Related: #1019, petry-projects/.github-private#1592, #1567, #657.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    automationAutomation improvements and gapsdev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions