Skip to content

Commit 5d4f98b

Browse files
CopilotricardoV94
andauthored
Format PR links in Discourse release notes to avoid redundant information (#7928)
Co-authored-by: ricardoV94 <[email protected]>
1 parent c7222f0 commit 5d4f98b

File tree

2 files changed

+168
-1
lines changed

2 files changed

+168
-1
lines changed

scripts/publish_release_notes_to_discourse.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
import os
4+
import re
45

56
import requests
67

@@ -58,6 +59,17 @@ def find_category_id(config: dict[str, str]) -> int:
5859
def format_release_content(config: dict[str, str]) -> tuple[str, str]:
5960
title = f"🚀 Release {config['RELEASE_TAG']}"
6061
repo_name = config["REPO_NAME"].split("/")[1]
62+
63+
# Format PR links in the release body
64+
# Replace https://github.com/pymc-devs/pymc/pull/123 with [#123](https://github.com/pymc-devs/pymc/pull/123)
65+
# This avoids redundant link rendering in Discourse
66+
# Use negative lookbehind to avoid formatting already-formatted links
67+
release_body = re.sub(
68+
r"(?<!\()\bhttps://github\.com/pymc-devs/pymc/pull/(\d+)\b",
69+
r"[#\1](\g<0>)",
70+
config["RELEASE_BODY"],
71+
)
72+
6173
content = f"""A new release of **{repo_name}** is now available!
6274
6375
## 📦 Release Information
@@ -69,7 +81,7 @@ def format_release_content(config: dict[str, str]) -> tuple[str, str]:
6981
7082
## 📋 Release Notes
7183
72-
{config["RELEASE_BODY"]}
84+
{release_body}
7385
7486
---
7587
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Copyright 2024 - present The PyMC Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import re
15+
16+
from publish_release_notes_to_discourse import format_release_content
17+
18+
19+
class TestFormatReleaseContent:
20+
def test_pr_links_are_formatted(self):
21+
"""Test that PR links are formatted correctly in the release body."""
22+
# Realistic release body from v5.26.0
23+
release_body = """<!-- Release notes generated using configuration in .github/release.yml at main -->
24+
25+
## What's Changed
26+
### Major Changes 🛠
27+
* Bump PyTensor dependency and drop support for NumPy <2.0, and Python 3.10 by @ricardoV94 in https://github.com/pymc-devs/pymc/pull/7910
28+
* Functions that try to infer inputs of the graph fail with more than one input. This includes `Model.compile_fn`, `gradient`, `jacobian` and `hessian_diag`.
29+
* `Model.compile_logp` now expects all model variables as input, even when only a subset of the logp terms is requested.
30+
* Many pytensor functions from moved from `pytensor.graph.basic` to `pytensor.graph.traversal`, including `ancestors`, `graph_inputs`, and toposort related functions.
31+
* Remove deprecated `noise` parameter for GPs by @williambdean in https://github.com/pymc-devs/pymc/pull/7886
32+
33+
### New Features 🎉
34+
* Implement `logcdf` for `CensoredRV` by @asifzubair in https://github.com/pymc-devs/pymc/pull/7884
35+
* Derive logprob for Split operation by @ricardoV94 in https://github.com/pymc-devs/pymc/pull/7875
36+
### Bugfixes 🪲
37+
* Fix bug in mixture logprob inference with `None` indices by @asifzubair in https://github.com/pymc-devs/pymc/pull/7877
38+
### Documentation 📖
39+
* Add model_to_mermaid to docs by @williambdean in https://github.com/pymc-devs/pymc/pull/7868
40+
* Use rst code-block over code:: by @williambdean in https://github.com/pymc-devs/pymc/pull/7882
41+
### Maintenance 🔧
42+
* Show more digits of step size in progress_bar by @ricardoV94 in https://github.com/pymc-devs/pymc/pull/7870
43+
* Allow for specification of 'var_names' in 'mock_sample' by @tomicapretto in https://github.com/pymc-devs/pymc/pull/7906
44+
45+
## New Contributors
46+
* @asifzubair made their first contribution in https://github.com/pymc-devs/pymc/pull/7871
47+
48+
**Full Changelog**: https://github.com/pymc-devs/pymc/compare/v5.25.1...v5.26.0"""
49+
50+
config = {
51+
"RELEASE_TAG": "v5.26.0",
52+
"REPO_NAME": "pymc-devs/pymc",
53+
"RELEASE_BODY": release_body,
54+
"RELEASE_URL": "https://github.com/pymc-devs/pymc/releases/tag/v5.26.0",
55+
}
56+
57+
title, content = format_release_content(config)
58+
59+
# Check that the title is correct
60+
assert title == "🚀 Release v5.26.0"
61+
62+
# Check that PR links in pymc-devs/pymc are formatted correctly
63+
assert "[#7910](https://github.com/pymc-devs/pymc/pull/7910)" in content
64+
assert "[#7886](https://github.com/pymc-devs/pymc/pull/7886)" in content
65+
assert "[#7884](https://github.com/pymc-devs/pymc/pull/7884)" in content
66+
assert "[#7875](https://github.com/pymc-devs/pymc/pull/7875)" in content
67+
assert "[#7877](https://github.com/pymc-devs/pymc/pull/7877)" in content
68+
assert "[#7868](https://github.com/pymc-devs/pymc/pull/7868)" in content
69+
assert "[#7882](https://github.com/pymc-devs/pymc/pull/7882)" in content
70+
assert "[#7870](https://github.com/pymc-devs/pymc/pull/7870)" in content
71+
assert "[#7906](https://github.com/pymc-devs/pymc/pull/7906)" in content
72+
assert "[#7871](https://github.com/pymc-devs/pymc/pull/7871)" in content
73+
74+
# Check that the raw PR link format is not present
75+
assert (
76+
"https://github.com/pymc-devs/pymc/pull/7910" in content
77+
) # it's still in the formatted link
78+
# But NOT as a standalone link (which would appear without the [#xxx](...) wrapper)
79+
# We can verify this by checking the pattern doesn't match the raw format
80+
# Find raw PR links (not inside markdown link syntax)
81+
raw_pr_links = re.findall(
82+
r"(?<!\()\bhttps://github\.com/pymc-devs/pymc/pull/\d+(?!\))", content
83+
)
84+
assert len(raw_pr_links) == 0, f"Found raw PR links: {raw_pr_links}"
85+
86+
# Check that other links remain unchanged (e.g., the Full Changelog link)
87+
assert (
88+
"**Full Changelog**: https://github.com/pymc-devs/pymc/compare/v5.25.1...v5.26.0"
89+
in content
90+
)
91+
92+
def test_non_pymc_links_unchanged(self):
93+
"""Test that PR links from other repositories are not affected."""
94+
release_body = """Some changes:
95+
* Feature from external repo in https://github.com/other-org/other-repo/pull/123
96+
* Our feature in https://github.com/pymc-devs/pymc/pull/456
97+
"""
98+
99+
config = {
100+
"RELEASE_TAG": "v1.0.0",
101+
"REPO_NAME": "pymc-devs/pymc",
102+
"RELEASE_BODY": release_body,
103+
"RELEASE_URL": "https://github.com/pymc-devs/pymc/releases/tag/v1.0.0",
104+
}
105+
106+
title, content = format_release_content(config)
107+
108+
# Check that pymc-devs/pymc PR link is formatted
109+
assert "[#456](https://github.com/pymc-devs/pymc/pull/456)" in content
110+
111+
# Check that other repo PR link is unchanged
112+
assert "https://github.com/other-org/other-repo/pull/123" in content
113+
assert "[#123](https://github.com/other-org/other-repo/pull/123)" not in content
114+
115+
def test_release_structure(self):
116+
"""Test that the overall release structure is correct."""
117+
config = {
118+
"RELEASE_TAG": "v1.2.3",
119+
"REPO_NAME": "pymc-devs/pymc",
120+
"RELEASE_BODY": "Test body with PR https://github.com/pymc-devs/pymc/pull/999",
121+
"RELEASE_URL": "https://github.com/pymc-devs/pymc/releases/tag/v1.2.3",
122+
}
123+
124+
title, content = format_release_content(config)
125+
126+
assert title == "🚀 Release v1.2.3"
127+
assert "A new release of **pymc** is now available!" in content
128+
assert "**Version:** `v1.2.3`" in content
129+
assert "**Repository:** [pymc-devs/pymc](https://github.com/pymc-devs/pymc)" in content
130+
assert "**Release Page:** https://github.com/pymc-devs/pymc/releases/tag/v1.2.3" in content
131+
assert "[#999](https://github.com/pymc-devs/pymc/pull/999)" in content
132+
133+
def test_already_formatted_links_not_double_formatted(self):
134+
"""Test that already-formatted PR links are not double-formatted."""
135+
release_body = """Some changes:
136+
* Already formatted: [#123](https://github.com/pymc-devs/pymc/pull/123)
137+
* Raw link: https://github.com/pymc-devs/pymc/pull/456
138+
"""
139+
140+
config = {
141+
"RELEASE_TAG": "v1.0.0",
142+
"REPO_NAME": "pymc-devs/pymc",
143+
"RELEASE_BODY": release_body,
144+
"RELEASE_URL": "https://github.com/pymc-devs/pymc/releases/tag/v1.0.0",
145+
}
146+
147+
title, content = format_release_content(config)
148+
149+
# Already formatted link should remain unchanged
150+
assert "[#123](https://github.com/pymc-devs/pymc/pull/123)" in content
151+
# Should NOT be double-formatted
152+
assert "[#123]([#123](https://github.com/pymc-devs/pymc/pull/123))" not in content
153+
154+
# Raw link should be formatted
155+
assert "[#456](https://github.com/pymc-devs/pymc/pull/456)" in content

0 commit comments

Comments
 (0)