Skip to content

Add helper to decide release notes reset for maintenance vs default branch #456

@Marenz

Description

@Marenz

Summary

Provide a helper function to centralize logic for deciding whether the RELEASE_NOTES.md file in downstream repos should be reset after tagging a release, especially when version ("default") branches like v1.x.x are used. The logic must not assume a main branch exists: many repos use a rolling version branch (vMAJOR.x.x) as the default working branch.

Motivation

At present we only develop and release from the default version branch (e.g. v1.x.x). As we evolve toward having multiple active maintenance branches (e.g. v1.4.x for fixes, while v1.x.x tracks upcoming minor work, and later v2.x.x becomes the new default), each repository would otherwise need custom Bash to decide:

  • Which branch a release tag (semantic vMAJOR.MINOR.PATCH) semantically belongs to.
  • Whether to reset the release notes on the branch that just produced the tag.
  • When to skip resetting (e.g. patch/minor released from a maintenance branch should not reset notes on the default version branch).

Centralizing this logic avoids duplication and simplifies transition from a single default version branch workflow to multiple maintenance branches.

Desired API (Proposal)

Add something like:

from dataclasses import dataclass
from typing import Optional

@dataclass
class ReleaseNotesResetDecision:
    tag: str                # e.g. 'v1.4.2'
    branch: str             # resolved branch (e.g. 'v1.4.x' or 'v1.x.x')
    perform_reset: bool     # whether to reset RELEASE_NOTES.md in that branch
    reason: str             # human explanation for logs


def compute_release_notes_reset(
    repo: Optional["git.Repo"] = None,
    tag: Optional[str] = None,
    default_branch: str | None = None,
) -> ReleaseNotesResetDecision:
    """Decide if/where to reset release notes for a given tag.

    Assumptions:
    - Repositories may use a version-pattern default branch like `v1.x.x` (no `main`).
    - Maintenance branches follow patterns: `vMAJOR.MINOR.x` (e.g. `v1.4.x`).
    - Optional long-lived major line branch pattern: `vMAJOR.x.x` (serving as the default branch) e.g. `v1.x.x`.

    Logic:
    1. Parse `tag` (`vX.Y.Z`).
    2. Candidate branches (in order): `vX.Y.x`, then `vX.x.x` (if not already default branch), then provided `default_branch` (if given and different), else raise if no matching head commit.
    3. Pick the first existing candidate whose HEAD commit equals the tag commit.
    4. `perform_reset` is True iff:
       * Chosen branch is a maintenance branch (`vX.Y.x`), OR
       * Chosen branch is the default version branch (`vX.x.x`) AND this is a new major release (`Y == 0 and Z == 0`).
       (So patch/minor releases on the default version branch do NOT reset.)
    5. Raise informative exception if tag commit doesn't match the chosen branch head.
    """
    ...

The return value can be consumed by a lightweight workflow script to decide whether to overwrite RELEASE_NOTES.md with the template.

Edge / Future Considerations

  • Pre‑release tags (v1.2.0-rc1) handling (likely always skip or separate flag) — future enhancement.
  • Allow customizing branch name patterns.
  • Could later extend to drive documentation versioning actions.

Implementation Notes

  • Reuse existing tag & branch parsing (BranchVersion.parse, to_semver).
  • Tests should cover:
    • Major release on default version branch (v2.0.0 on v2.x.x) -> reset.
    • Minor release on default version branch (v1.4.0 on v1.x.x) when no v1.4.x yet -> no reset.
    • Minor release on newly created maintenance branch (v1.4.0 tag on v1.4.x) -> reset.
    • Patch release on maintenance branch (v1.4.2 on v1.4.x) -> reset.
    • Patch release when only default version branch exists (v1.4.2 on v1.x.x) -> no reset.
  • Provide clear exceptions when the tag commit mismatches all candidate branch heads.

Acceptance Criteria

  • Helper implemented with docstring and typing.
  • Decision matrix tested for scenarios above.
  • Example usage snippet (GitHub Actions) in docs/README.

Example Outcome Table (abridged)

Tag Branches present Resolved branch perform_reset Reason
v2.0.0 v2.x.x v2.x.x True New major on default version branch
v1.4.0 v1.x.x v1.x.x False Minor on default version branch (no maintenance yet)
v1.4.0 v1.x.x, v1.4.x v1.4.x True Maintenance branch minor release
v1.4.2 v1.x.x, v1.4.x v1.4.x True Maintenance branch patch release
v1.4.2 v1.x.x v1.x.x False Patch on default version branch

Let me know if you prefer alternative naming or additional signals in the decision object (e.g. enum for branch kind).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions