Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
92b3cbf
Bump version to 2026.3.0-dev
jesserockz Feb 12, 2026
286b088
[mipi_spi] Add Waveshare 1.83 v2 panel (#6019)
schdro Feb 12, 2026
0519835
Merge branch 'beta' into next
jesserockz Feb 12, 2026
28e42db
Hugo to Starlight migration (#6037)
mrdarrengriffin Feb 13, 2026
c97a158
[bl0942] Update docs to match esphome PR#12867 (#6075)
DjordjeMandic Feb 13, 2026
bd542af
[changelog] Add 2026.2.0 release highlights and breaking changes (#6070)
bdraco Feb 13, 2026
a45f5d1
Fix malformed links and add missing image in component index (#6076)
swoboda1337 Feb 13, 2026
89b0830
Fix blank guides/changelog and guides index pages (#6077)
swoboda1337 Feb 13, 2026
237013f
Prefix APIRef links with "API Reference:" (#6081)
swoboda1337 Feb 14, 2026
c47b7cb
Merge branch 'beta' into next
jesserockz Feb 14, 2026
4ec1bb5
Make changelog index a real searchable page (#6083)
swoboda1337 Feb 14, 2026
5ef130d
[remote_transmitter/remote_receiver/esp32_rmt_led_strip] Document ESP…
swoboda1337 Feb 15, 2026
4c3d66e
Fix changelog redirect to preserve URL hash fragment (#6088)
swoboda1337 Feb 15, 2026
4fd3078
[combination] Fix 'coeffecient' typo to 'coefficient' in docs (#6087)
swoboda1337 Feb 15, 2026
600c599
[epaper_spi] Add WeAct 3-color e-paper displays (#6053)
pgolawsk Feb 15, 2026
1aac5ae
[epaper_spi] Add Waveshare 7.5in e-Paper (H) to supported panels (#6085)
corneliusludmann Feb 16, 2026
625609f
Merge branch 'beta' into next
jesserockz Feb 17, 2026
238febe
[sensor] Add filter headings to table of contents (#6102)
swoboda1337 Feb 17, 2026
62ad725
Remove Hugo leftovers and update dev tooling for Starlight (#6078)
swoboda1337 Feb 17, 2026
0eff2a4
Remove Docker development environment (#6103)
swoboda1337 Feb 17, 2026
a704a6d
Remove dangling postCreate.sh file (#6105)
jesserockz Feb 17, 2026
9a92ef3
Remove assets symlink (#6106)
jesserockz Feb 17, 2026
ddf118b
Auto-generate All Actions/Conditions lists from doc headings (#6107)
swoboda1337 Feb 17, 2026
bb486cc
[docs] Add linter check for automation headings and fix sprinkler (#6…
swoboda1337 Feb 17, 2026
8450f14
Merge branch 'beta' into next
jesserockz Feb 18, 2026
ee8dbfe
Link domain names to component pages in automation lists (#6111)
swoboda1337 Feb 18, 2026
fe3bd8f
Merge branch 'beta' into next
jesserockz Feb 18, 2026
b56bf5d
Merge branch 'current' into next
jesserockz Feb 18, 2026
5ffe307
[esp32_camera] Add support for sensors without JPEG support (#5104)
mback2k Feb 19, 2026
1b08439
[faq] Add brownout detector troubleshooting section (#6122)
swoboda1337 Feb 19, 2026
f10f00d
Restore height limit on images in component pages. (#6120)
clydebarrow Feb 19, 2026
75839e8
Merge branch 'current' into next
swoboda1337 Feb 20, 2026
04c8eff
[cc1101] documentation of actions allowing configuration changes (#6124)
sxtfov Feb 21, 2026
a6dd81a
[mqtt] Remove broken ESP8266 ssl_fingerprints documentation (#6134)
bdraco Feb 21, 2026
d2edff1
[wifi] Add band_mode documentation for ESP32-C5 dual-band WiFi (#6125)
swoboda1337 Feb 21, 2026
ec8f0f5
[modbus_controller] Update EPEVER example to use ESPTime API (#6011)
bdraco Feb 22, 2026
f465aa4
[nrf52,logger] Early debug (#5906)
tomaszduda23 Feb 22, 2026
10761ad
[hdc302x] New component docs (#6135)
joshuasing Feb 23, 2026
d7168d1
[version] text sensor add option `hide_hash` to restore the pre-2026.…
nagyrobi Feb 24, 2026
d935528
[mipi_dsi] update transform docs (#6140)
clydebarrow Feb 24, 2026
c7ee651
[esp32] Document engineering_sample option for ESP32-P4 (#6123)
swoboda1337 Feb 24, 2026
e44f78c
Document esp32_ble_server max_clients option (#6148)
RAR Feb 24, 2026
4786288
Merge branch 'current' into next
jesserockz Feb 26, 2026
e42447e
Merge branch 'current' into next
jesserockz Feb 26, 2026
bdba762
Add undocumented API changes and auto-generated upgrade checklist to …
bdraco Feb 26, 2026
c8bc810
[esp_ldo] Document passthrough (#6133)
p1ngb4ck Feb 26, 2026
4df9ea2
[mipi_dsi] Add section for standalone displays and add 5 Waveshare pa…
gtjoseph Feb 27, 2026
2310b12
[esp32_ble] Add documentation for ble security parameters (#5769)
whitty Feb 27, 2026
2ba4491
[esp32_hosted] Add configurable SDIO clock frequency (#6168)
deirdreobyrne Feb 27, 2026
7c7df1a
[safe_mode] Add mark_boot_ok documentation (#6157)
mcassaniti Feb 27, 2026
7b6db20
[esp32] Update `execute_from_psram` docs (#6164)
clydebarrow Feb 27, 2026
0374413
[media_Player] Document new actions/conditions (#6101)
kahrendt Feb 27, 2026
f4d93a7
[speaker] Document support for decoding Opus audio (#6071)
kahrendt Feb 27, 2026
26d5d43
[gt911] Add configuration notes for interrupt pin (#6136)
PedanticAvenger Feb 28, 2026
211a0ed
Sen6x (#5801)
mebner86 Feb 28, 2026
56fb399
[mipi_dsi] Shorten display text of URLs to prevent wrapping. (#6160)
gtjoseph Mar 1, 2026
0d43861
[esp32_touch] Add ESP32-P4 support, document voltage_attenuation as E…
swoboda1337 Mar 2, 2026
e6156d1
Merge branch 'current' into next
jesserockz Mar 2, 2026
682855b
Merge branch 'current' into next
jesserockz Mar 2, 2026
f877ac7
[media_source] Initial platform component index (#6197)
kahrendt Mar 3, 2026
54e8b0f
[lps22] Note support for the LPS22DF variant (#6189)
melak Mar 3, 2026
23a7bb1
[openthread] Document output_power (#6175)
schdro Mar 3, 2026
8b27b5f
[pid] Document deadband multiplier action and sensor types
ngolf Mar 12, 2026
a40d592
Merge branch 'current' into pid-runtime-deadband-actions-docs-next
ngolf Mar 12, 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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*.mp3 binary
*.gif binary
*.avif binary
*.webp binary
1 change: 1 addition & 0 deletions public/images/hdc302x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/sen6x.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 61 additions & 18 deletions script/generate_release_notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
LABEL_BREAKING_CHANGE = "breaking-change"
LABEL_NEW_FEATURE = "new-feature"
LABEL_NEW_COMPONENT = "new-component"
LABEL_UNDOCUMENTED_API_CHANGE = "undocumented-api-change"


@dataclass
Expand Down Expand Up @@ -567,6 +568,9 @@ def generate_prompts(self, prs: list[PullRequest]) -> None:
breaking_changes = [pr for pr in prs if LABEL_BREAKING_CHANGE in pr.labels]
new_features = [pr for pr in prs if LABEL_NEW_FEATURE in pr.labels]
new_components = [pr for pr in prs if LABEL_NEW_COMPONENT in pr.labels]
undocumented_api_changes = [
pr for pr in prs if LABEL_UNDOCUMENTED_API_CHANGE in pr.labels
]

# Generate Combined Overview + Feature Highlights Prompt
overview_and_highlights_prompt = self._generate_overview_and_highlights_prompt(
Expand All @@ -575,13 +579,13 @@ def generate_prompts(self, prs: list[PullRequest]) -> None:
overview_highlights_file = self.prompts_dir / "overview_and_highlights.txt"
overview_highlights_file.write_text(overview_and_highlights_prompt)

# Generate Combined Breaking Changes Prompt (user + developer)
if breaking_changes:
breaking_prompt = self._generate_combined_breaking_changes_prompt(
breaking_changes
)
breaking_file = self.prompts_dir / "breaking_changes.txt"
breaking_file.write_text(breaking_prompt)
# Generate Breaking Changes + Upgrade Checklist + Undocumented API Changes Prompt
# Always generated because the Upgrade Checklist is always needed
breaking_prompt = self._generate_breaking_changes_and_checklist_prompt(
breaking_changes, undocumented_api_changes, prs
)
breaking_file = self.prompts_dir / "breaking_changes.txt"
breaking_file.write_text(breaking_prompt)

# Print instructions
print("\n" + "=" * 80)
Expand All @@ -590,21 +594,24 @@ def generate_prompts(self, prs: list[PullRequest]) -> None:
print("\nStart Claude Code CLI and read the prompt files:\n")
print(" claude")
print(f" > Please read {overview_highlights_file} and follow the instructions")
if breaking_changes:
print(f" > Please read {breaking_file} and follow the instructions")
print(f" > Please read {breaking_file} and follow the instructions")

print("\nPrompt 1: Overview + Feature Highlights (COMBINED)")
print(f" Prompt: {overview_highlights_file}")
print(f" Outputs: {self.responses_dir / 'release_overview.md'}")
print(f" {self.responses_dir / 'feature_highlights.md'}")

if breaking_changes:
print("\nPrompt 2: Breaking Changes - Users + Developers (COMBINED)")
print(f" Prompt: {breaking_file}")
print(f" Outputs: {self.responses_dir / 'breaking_changes_users.md'}")
print(f" {self.responses_dir / 'breaking_changes_developers.md'}")
print(
"\nPrompt 2: Breaking Changes + Upgrade Checklist + Undocumented API Changes"
)
print(f" Prompt: {breaking_file}")
print(f" Outputs: {self.responses_dir / 'breaking_changes_users.md'}")
print(f" {self.responses_dir / 'breaking_changes_developers.md'}")
print(f" {self.responses_dir / 'upgrade_checklist.md'}")
if undocumented_api_changes:
print(f" {self.responses_dir / 'undocumented_api_changes.md'}")

print("\nNote: Each prompt will generate TWO output files automatically.")
print("\nNote: Each prompt will generate multiple output files automatically.")

print("\n" + "=" * 80)
print("STEP 2: Assemble the changelog")
Expand Down Expand Up @@ -654,18 +661,25 @@ def _generate_overview_and_highlights_prompt(
breaking_changes=breaking_changes,
)

def _generate_combined_breaking_changes_prompt(
self, breaking_prs: list[PullRequest]
def _generate_breaking_changes_and_checklist_prompt(
self,
breaking_prs: list[PullRequest],
undocumented_api_prs: list[PullRequest],
all_prs: list[PullRequest],
) -> str:
"""Generate combined prompt for both user and developer breaking changes"""
"""Generate prompt for breaking changes, upgrade checklist, and undocumented API changes"""
template = self.jinja_env.get_template("breaking_changes.txt")

return template.render(
version=str(self.version),
users_file=self.responses_dir / "breaking_changes_users.md",
devs_file=self.responses_dir / "breaking_changes_developers.md",
checklist_file=self.responses_dir / "upgrade_checklist.md",
undocumented_file=self.responses_dir / "undocumented_api_changes.md",
prs_cache_dir=self.prs_cache_dir,
breaking_changes=breaking_prs,
undocumented_api_changes=undocumented_api_prs,
all_prs=all_prs,
)

def assemble_changelog(self) -> bool:
Expand Down Expand Up @@ -731,6 +745,16 @@ def assemble_changelog(self) -> bool:
if highlights_file.exists():
highlights = highlights_file.read_text().strip()

upgrade_checklist_file = self.responses_dir / "upgrade_checklist.md"
upgrade_checklist = ""
if upgrade_checklist_file.exists():
upgrade_checklist = upgrade_checklist_file.read_text().strip()

undocumented_api_file = self.responses_dir / "undocumented_api_changes.md"
undocumented_api = ""
if undocumented_api_file.exists():
undocumented_api = undocumented_api_file.read_text().strip()

# Load the PR numbers for this version from a manifest file
manifest_file = self.version_dir / "pr_numbers.txt"
if not manifest_file.exists():
Expand All @@ -754,6 +778,11 @@ def assemble_changelog(self) -> bool:
# Replace AI-generated sections
template = self._replace_marker_content(template, "RELEASE_OVERVIEW", overview)

if upgrade_checklist:
template = self._replace_marker_content(
template, "UPGRADE_CHECKLIST", upgrade_checklist
)

if highlights:
template = self._replace_marker_content(
template, "FEATURE_HIGHLIGHTS", highlights
Expand All @@ -764,6 +793,11 @@ def assemble_changelog(self) -> bool:
template, "BREAKING_CHANGES_USERS", breaking_users
)

if undocumented_api:
template = self._replace_marker_content(
template, "UNDOCUMENTED_API_CHANGES", undocumented_api
)

if breaking_devs:
template = self._replace_marker_content(
template, "BREAKING_CHANGES_DEVELOPERS", breaking_devs
Expand Down Expand Up @@ -828,11 +862,15 @@ def _generate_auto_sections(self, template: str, prs: list[PullRequest]) -> str:
new_features = [pr for pr in prs if "new-feature" in pr.labels]
new_components = [pr for pr in prs if "new-component" in pr.labels]
breaking_changes = [pr for pr in prs if "breaking-change" in pr.labels]
undocumented_api_changes = [
pr for pr in prs if "undocumented-api-change" in pr.labels
]

# Generate lists
features_list = self._format_pr_list(new_features)
components_list = self._format_pr_list(new_components)
breaking_list = self._format_pr_list(breaking_changes)
undocumented_list = self._format_pr_list(undocumented_api_changes)
all_list = self._format_pr_list(prs)

# Replace sections
Expand All @@ -845,6 +883,11 @@ def _generate_auto_sections(self, template: str, prs: list[PullRequest]) -> str:
template = self._replace_marker_content(
template, "AUTO_GENERATED_BREAKING_CHANGES_LIST", breaking_list
)
template = self._replace_marker_content(
template,
"AUTO_GENERATED_UNDOCUMENTED_API_CHANGES_LIST",
undocumented_list,
)
return self._replace_marker_content(
template, "AUTO_GENERATED_ALL_CHANGES", all_list
)
Expand Down
Loading
Loading