Skip to content

chore: rename release branch main->release in-repo (w1-w4)#1027

Open
joeharris76 wants to merge 3 commits into
developfrom
chore/rename-main-to-release-in-repo
Open

chore: rename release branch main->release in-repo (w1-w4)#1027
joeharris76 wants to merge 3 commits into
developfrom
chore/rename-main-to-release-in-repo

Conversation

@joeharris76

Copy link
Copy Markdown
Owner

Description

Decision B of the branching-strategy review (rename-release-branch-main-to-release). main is already the release-only branch — validate-*-pr.yml rejects any PR whose head is not a vX.Y.Z branch, release-finalize fast-forwards + tags it, and its HEAD is always the exact latest-release commit. release is the accurate name.

This PR lands the IN-REPO half only (work units w1-w4). The GitHub-side branch rename and ruleset recreation (w5/w6) are maintainer-only GitHub admin actions and are NOT performed here — no GitHub admin/settings change was made in this session. The TODO item stays In Progress with w5/w6 pending. The full ordered migration is documented in the new docs/operations/branch-rename-runbook.md.

What changed

  • w1 — workflows. mainrelease triggers in lint.yml, test.yml, perf-smoke.yml, docs.yml (incl. the Pages deploy gate refs/heads/mainrefs/heads/release), results-explorer-browser.yml. Functional/careful paths: release.yml's verify-tag-on-main job renamed to verify-tag-on-release (job name, needs: refs, git fetch origin release, all origin/release ancestor checks) — the tag-shaped-ref PyPI publish condition startsWith(github.ref, 'refs/tags/v') is untouched; test.yml's six base_ref == 'main' / != 'main' release-gating conditionals (compat-test, integration-smoke, integration, correctness-gate, release-readiness, release-required-result) → 'release' (the != 'develop' checks left as develop); validate-main-pr.yml renamed to validate-release-pr.yml (+ internal strings, RELEASE_CANARY_BRANCH).
  • w2 — Makefile. release-cut/release-finalize base branch (--base main--base release), checkout/pull, generate_changelog_entry --since-ref origin/mainorigin/release, ruleset-name text, help text, and the develop|main branch-protection guards. MAIN_CLONE / "main clone" worktree-pool concept left untouched (unrelated to the branch name).
  • w3 — docs/templates. release-guide.md, RELEASE_PR_TEMPLATE.md, CONTRIBUTING.md, repo-admin-settings.md (release-identity refs only — the default-branch-scheduling section is left as-is with an added caveat note, since scheduled-workflow behavior tracks the default branch, which Decision A changes separately), results-phase-2-runbook.md (explorer Pages-deploy gate refs). landing/index.html footer blob/mainblob/release. Blog blob/main links pinned to the matching release tags (duckdb-tpch → v0.1.4; the two v0.2.1 posts → v0.2.1), each verified with git cat-file -e <tag>:<path>.
  • w4 — new docs/operations/branch-rename-runbook.md. Ordered migration (Decision A default-switch → this PR → Decision B admin rename), the no-real-gap reasoning, verification, rollback, and the verified-safe notes (PyPI trusted publishing and GitHub Pages are branch-independent).

Ordering caveat (maintainer, please sequence w5/w6 right after merge)

Merging this to develop flips the tree to refer to the release branch as release before the GitHub branch is actually renamed. This is documented-safe: the release branch only ever receives pushes via release-cut / release-finalize, both maintainer-controlled. As long as no release is cut between this merge and the branch rename, there is no real gap. Right after merging, please execute w5/w6 per the runbook: set default_branch=develop (Decision A, if not already done), then gh api -X POST .../branches/main/rename -f new_name=release, recreate the main-release-only ruleset as release-only on refs/heads/release (same required checks/protections), and update the ruleset-id reference in repo-admin-settings.md. If make release-cut is accidentally run in the interim it fails fast (gh pr create --base release 404s) — no release is silently mis-cut.

Review outcome (Opus 4.8 release-criticality review)

An independent adversarial review was run focused on the publish path. Verdict: release-safe.

  • PyPI publish gate integrity: PASS — real-PyPI publish (release.yml L158) still gated by test_pypi != 'true' && startsWith(github.ref, 'refs/tags/v'), not loosened; verify-tag-on-mainverify-tag-on-release complete and self-consistent.
  • test.yml base_ref conditionals: PASS — all six release-gating conditionals renamed to 'release', none missed, no != 'develop' check wrongly touched, no double-renames.
  • Over-eager/missed renames: no false renames (MAIN_CLONE, _project/TODO/main/… paths, blog English prose, and pyproject.toml's blob/main/CHANGELOG.md — out of this TODO's scope_limit — all correctly untouched). One doc miss was surfaced and fixed in this PR (results-phase-2-runbook.md stale deploy-gate refs).

Two maintainer notes (out of scope for this TODO, left deliberately):

  1. pyproject.toml Changelog URL still blob/main/CHANGELOG.md — outside this TODO's scope_limit; GitHub redirects renamed-branch blob URLs after w6, so it resolves. Its pinning test is unchanged.
  2. .github/workflows/seed-corpus.yml opens PRs with --base main from chore/seed-corpus-* heads carrying dev-only results-data/bundles/ content (curated off the release branch). This is not release-branch identity — renaming it to release would be wrong (a chore/ head can't merge to the release-only branch). It reads as integration-branch semantics and likely belongs to the Decision A default-switch item; flagged for the maintainer.

Verification

  • uv run -- python -c "import yaml,glob; [yaml.safe_load(...) for f in glob('.github/workflows/*.yml')]"all workflows parse.
  • grep -rn 'refs/heads/main' .github/workflowsempty; grep -rn -- '--base main' Makefileempty; grep 'base release' Makefile → present in release-cut + release-finalize.
  • Blog tag pins resolve: git cat-file -e v0.1.4:benchbox/core/tpch/*.py (5 paths) and git cat-file -e v0.2.1:CHANGELOG.md all succeed.
  • tests/unit/test_release_infrastructure.py38 passed, 2 deselected.
  • todo_cli validate + check-graphgreen (107 items).

Type of Change

Chore / release tooling + docs (naming clarity, no behavioral change).

Notes

  • Touches release.yml → CODEOWNERS-gated (@joeharris76). This PR must wait for Code Owner review and be sequenced with the coordinated GitHub-side branch rename (w5/w6). Auto-merge is intentionally NOT enabled.
  • No GitHub admin/settings action was taken in this session; w5/w6 remain the maintainer's to execute per the runbook.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JFdZAbavgrKaNLe4YZa3zf


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9aff33d43a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/validate-release-pr.yml Outdated
Comment thread docs/operations/repo-admin-settings.md
joeharris76 added a commit that referenced this pull request Jul 7, 2026
Creates _project/TODO/main/active/human-action-required.yaml — a single running
index of actions only the human maintainer can perform (GitHub repo-admin
changes, Code-Owner reviews, human recruitment), which agents in this project
cannot do (the sandbox git remote rejects branch/default-branch changes, admin
APIs are out of scope, CODEOWNERS review must be human).

Seeded with the current queue:
- w1: Code-Owner review + merge PR #1027 (in-repo main->release rename).
- w2 (needs w1): GitHub-side branch rename main->release + ruleset recreate.
- w3: set default_branch=develop (+ verify scheduled workflows) — also activates
  the §2.8 workflow_run companion and the release-canary cron.
- w4: recruit one external contributor for the Phase-2 submission dry-run.
- w5 (optional): delete the 5 dead orphan branches (agent couldn't; harmless —
  they're allowlisted for the orphaned-commit detector).

Each work unit cross-references its authoritative source TODO and gives the
exact command. New maintainer/human actions get appended here so there is one
place to see what's waiting on the maintainer. todo validate + check-graph green.


Claude-Session: https://claude.ai/code/session_01JFdZAbavgrKaNLe4YZa3zf

Co-authored-by: Claude <noreply@anthropic.com>
joeharris76 added a commit that referenced this pull request Jul 10, 2026
…ut (#1089)

main and develop have unrelated roots (Phase 4 filter-merge) and diverge
permanently: main carries one squash commit per release that develop never
sees, and the 2026-04-27 amendment removed A4 step 6 (rebase develop onto
main). A vX.Y.Z branch cut cleanly from develop is therefore not mergeable
into main -- GitHub cannot compute a merge ref, so the release PR sits at
CONFLICTING and *no CI runs at all*: neither validate-base nor
release-required-result ever trigger.

Every cut before v0.3.1 (#711, #712, #1029, #1043, #1072) worked around this
by hand. release-cut now performs the merge itself, between the
"Release vX.Y.Z" commit and the push.

-s ours records origin/main as a second parent while preserving the curated
release tree byte-for-byte; release-finalize's squash-merge then collapses
the branch to a single commit, so the merge never reaches main's
release-only ledger. Verified: after the merge, merge-base(origin/main, HEAD)
== origin/main, so GitHub's three-dot PR diff is exactly the release delta.

The recipe guards the merge by asserting the tree hash is unchanged across
it. A -s ours merge cannot change the tree by construction, so the guard is
really an assertion that the strategy is still ours -- any other strategy
drags main-only content back into the curated tree, silently un-curating the
release. The guard is also a no-op-safe check: if origin/main is already an
ancestor, git reports "Already up to date", the tree is unchanged, and the
cut proceeds.

--no-verify: git merge fires pre-merge-commit (not pre-commit). That hook is
not in default_install_hook_types today, so this is defensive -- but curation
has already deleted .pre-commit-config.yaml and the repo:local hook
entrypoints by this point, so installing it later would otherwise break every
cut here.

Ordering is load-bearing: the merge must follow generate_changelog_entry.py
--since-ref origin/main, which needs main to still be a non-ancestor, and
must precede the push, or the PR is born CONFLICTING again. The new
regression test pins all three positions plus the strategy flags.

Coordination with #1027 (rename main -> release): this change uses the literal
origin/main spelling that the rest of the Makefile already uses, so that PR's
textual rename sweep picks these lines up with the existing ones. Expect a
mechanical conflict in the release-cut header comment (step renumbering).

Co-authored-by: Joe Harris <57046+joeharris76@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
claude and others added 3 commits July 10, 2026 08:25
Decision B of the branching-strategy review: `main` is already the
release-only branch (validate-*-pr.yml rejects non-vX.Y.Z heads,
release-finalize fast-forwards+tags it). `release` is the accurate name.

This lands the IN-REPO half only (work units w1-w4); the GitHub-side
branch rename + ruleset recreation (w5/w6) are maintainer-only admin
actions, left pending per docs/operations/branch-rename-runbook.md.

- w1 workflows: lint/test/perf-smoke/docs/results-explorer-browser
  triggers main->release; docs.yml Pages deploy gate refs/heads/main->
  release; release.yml verify-tag-on-main->verify-tag-on-release (job,
  origin/release ancestor checks) — the tag-shaped-ref PyPI publish
  condition is untouched; test.yml's six base_ref=='main'/!='main'
  release-gating conditionals->release; validate-main-pr.yml renamed to
  validate-release-pr.yml (+ internal strings, RELEASE_CANARY_BRANCH).
- w2 Makefile: release-cut/release-finalize base branch, checkout/pull,
  --since-ref origin/release, ruleset-name text, help text, and the
  develop|main branch-protection guards. MAIN_CLONE / "main clone"
  worktree-pool concept left untouched (unrelated to the branch name).
- w3 docs/templates: release-guide.md, RELEASE_PR_TEMPLATE.md,
  CONTRIBUTING.md, repo-admin-settings.md (release-identity refs only;
  the default-branch-scheduling section left as-is with a caveat note),
  results-phase-2-runbook.md; landing/index.html footer blob/main->
  blob/release; blog blob/main links pinned to release tags (v0.1.4,
  v0.2.1) verified with git cat-file.
- w4 new docs/operations/branch-rename-runbook.md: ordered migration,
  no-real-gap reasoning, verification, rollback, PyPI/Pages branch-
  independence.

Verification: all workflows parse; grep for refs/heads/main in workflows
and --base main in Makefile both empty; tests/unit/test_release_
infrastructure.py 38 passed; todo validate + check-graph green.

Item stays In Progress (w5/w6 admin pending). release.yml is touched so
this PR is CODEOWNERS-gated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JFdZAbavgrKaNLe4YZa3zf
…heck's hardcoded old name

Two review findings on the main->release in-repo rename:

- validate-release-pr.yml set RELEASE_CANARY_BRANCH=release, but
  release-canary.yml's scheduled runs report the branch they were
  TRIGGERED from (the repository default, which this migration moves
  to develop), not RELEASE_CANARY_REF's checkout target. Left as
  "release", every release PR's validate-base would fail to find any
  canary runs. Changed to "develop", matching RELEASE_CANARY_REF/
  RELEASE_CANARY_CHECKED_REF already in the same env block.

- scripts/ruleset_drift_check.py's parse_expected_rulesets still
  hardcoded the old "main-release-only" name, but the runbook renamed
  the section to "release-only". Reproduced the exact crash this would
  cause (ValueError: could not find ruleset section for
  'main-release-only') via git stash before fixing. Updated the two
  test files that keyed off the old name to match.

Verified via git stash that all touched tests fail without these fixes.
The w1-w4 rename moved validate-main-pr.yml -> validate-release-pr.yml but
left four comment/docstring pointers at the old path, plus origin/main as the
--since-ref example now that release-cut passes origin/release.

repo-admin-settings.md's pointer arrived from develop after this branch was
cut, in a hunk this branch never touched, so the rebase merged it without a
conflict.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@joeharris76 joeharris76 force-pushed the chore/rename-main-to-release-in-repo branch from 8f45fb5 to 8522021 Compare July 10, 2026 12:32
joeharris76 added a commit that referenced this pull request Jul 10, 2026
* fix(ci): retarget seed-corpus PR from main to develop

`seed-corpus.yml` opened its automated bundle PR with `--base main`. That
was already broken: the head it pushes is `chore/seed-corpus-<date>-<run>`,
and `validate-main-pr.yml` rejects any PR into `main` whose head is not a
`vX.Y.Z` release branch. It would also hard-fail outright once the
main -> release rename (PR #1027) removes the `main` branch.

`develop` is the intended base: `sync-results-data-to-published.yml`
triggers on pushes to `develop` under `results-data/bundles/**` and
documents "a maintainer-run seed corpus refresh from `seed-corpus.yml`"
as its motivating case. Correct the PR body's "Merging" section to match
that flow -- it claimed the merge triggers `docs`, which only fires on
pushes to the release branch.

The workflow is `workflow_dispatch`-only and `release-cut` curates it out
of the release tree, so no CI job covers this. Add unit tests pinning the
base to `develop` and encoding why a `chore/` head can never target the
release branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): unescape backticks in seed-corpus PR body

The body is built with a quoted heredoc (`<<'EOF'`), so the shell performs
no expansion inside it. The `\`` escapes were therefore not protecting
anything -- they rendered as literal backslashes in the PR body. Drop them
and add a guard test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Joe Harris <57046+joeharris76@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants