Skip to content
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c5c6190
Remove update_github_links.py
janniklasrose Aug 26, 2026
6a9f7d3
Update validate_nextchanges.py
janniklasrose Aug 26, 2026
2eeb831
Make changelog-preview pass PR number and --strict flag to validate_n…
janniklasrose Aug 26, 2026
8e9768b
Documentation
janniklasrose Aug 26, 2026
2e51904
TEST ONLY: add test fragments
janniklasrose Aug 27, 2026
7f4fbc8
Fix test4 which should be happy path
janniklasrose Aug 27, 2026
7909e2a
Merge remote-tracking branch 'origin/main' into janniklasrose/nextcha…
janniklasrose Aug 27, 2026
99d5458
Correctly attribute trailing parentheses group with wrong link vs tra…
janniklasrose Aug 27, 2026
6b463c6
Remove test files
janniklasrose Aug 27, 2026
bd6956d
Infer cli args from CI env var and PR_NUMBER (added to workflow)
janniklasrose Sep 1, 2026
a4c33b3
Surface gh error when branch PR detection fails
janniklasrose Sep 1, 2026
8baa901
Add --fix for nextchanges
janniklasrose Sep 1, 2026
8f8903a
Merge remote-tracking branch 'origin/main' into janniklasrose/nextcha…
janniklasrose Sep 1, 2026
6a8f368
Fix existing violations
janniklasrose Sep 1, 2026
2983fbb
Merge remote-tracking branch 'origin/main' into janniklasrose/nextcha…
janniklasrose Sep 1, 2026
9b06a48
Fix more files
janniklasrose Sep 1, 2026
078c1af
More fixes
janniklasrose Sep 1, 2026
7a06f0c
Merge remote-tracking branch 'origin/janniklasrose/nextchanges-enforc…
janniklasrose Sep 1, 2026
95e2a12
Auto-fix by default
janniklasrose Sep 1, 2026
4de92b0
Merge remote-tracking branch 'origin/main' into janniklasrose/nextcha…
janniklasrose Sep 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions tools/validate_nextchanges.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,49 @@ def has_fragments(changelog_dir):
return any(p.name != README for p in changelog_dir.glob("*/*.md"))


def fragment_paths(changelog_dir):
"""The section fragments under ``changelog_dir`` (README.md excluded), sorted."""
return sorted(p for p in changelog_dir.glob("*/*.md") if p.name != README)


def fixed_fragment(text, pr):
r"""Return ``text`` with a trailing PR link for ``pr`` appended, or unchanged.

Only a well-formed fragment (single line, ``* `` bullet, trailing period) with
no trailing link group is changed; anything else is returned unchanged for the
linter to report, so the fix never guesses at a malformed entry.

>>> fixed_fragment("* Added a thing.\n", "42")
'* Added a thing. ([#42](https://github.com/databricks/cli/pull/42))\n'
>>> fixed_fragment("* Already linked. ([#7](https://github.com/databricks/cli/pull/7))\n", "42")
'* Already linked. ([#7](https://github.com/databricks/cli/pull/7))\n'
>>> fixed_fragment("No bullet.\n", "42")
'No bullet.\n'
"""
stripped = text.strip()
if fragment_format_problem(text) is not None or TRAILING_GROUP_RE.search(stripped):
return text
return f"{stripped} ([#{pr}](https://github.com/databricks/cli/pull/{pr}))\n"


def autofix(changelog_dir, root):
"""Append the branch's PR link to fragments missing one (a lint autofix).

The PR is inferred from the current branch (local only; see
``current_branch_pr``). Prints each file changed. Silently does nothing when
the branch has no PR yet — the number can't be inferred, so there's nothing
to add — since this runs by default on every validation."""
pr = current_branch_pr(root)
if pr is None:
return
for path in fragment_paths(changelog_dir):
text = path.read_text(encoding="utf-8")
fixed = fixed_fragment(text, pr)
if fixed != text:
path.write_text(fixed, encoding="utf-8")
print(f"Fixed {path.relative_to(root)}: added ([#{pr}](.../pull/{pr}))")


def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--root", type=pathlib.Path, default=pathlib.Path.cwd(), help="repository root")
Expand All @@ -348,6 +391,11 @@ def main(argv=None):

sections = load_sections(args.root)

# Auto-fix by default: add the branch's PR link to fragments missing one
# before validating. A no-op in CI and anywhere the branch has no PR.
if has_fragments(changelog_dir):
autofix(changelog_dir, args.root)

# A trailing PR link is required whenever the change is associated with a PR:
# always in CI (fail closed), and locally when the branch has an open PR.
# ``fallback_pr`` is the PR to expect for not-yet-merged fragments — the
Expand Down