From 232ee2ce21ba8d23092c1adb2ab8771ad97c5d4b Mon Sep 17 00:00:00 2001 From: TrinaxCode <185935802+TrinaxCode@users.noreply.github.com> Date: Mon, 26 Oct 2026 02:36:58 -0600 Subject: [PATCH] docs: date the 1.4.0 changelog, add known limits and publish the changelog as release notes The 1.4.0 heading said 2026-10-23 although the section was edited until the tag day; it now carries the release date. Known limits (code questions with small models, slow research on CPU, what was not measured) are listed in both changelogs and READMEs. The release workflow used --generate-notes, which lists PR titles and would drop those limits. It now publishes the version's CHANGELOG section (scripts/release_notes.py) and fails when the section is missing or empty. Co-Authored-By: Claude Sonnet 5.5 Signed-off-by: TrinaxCode <185935802+TrinaxCode@users.noreply.github.com> --- .github/workflows/release.yml | 11 +++++- README.es.md | 10 +++++ README.md | 10 +++++ docs/CHANGELOG.es.md | 12 +++++- docs/CHANGELOG.md | 12 +++++- scripts/release_notes.py | 48 ++++++++++++++++++++++++ tests/test_release_notes.py | 69 +++++++++++++++++++++++++++++++++++ tests/test_scripts.py | 4 +- 8 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 scripts/release_notes.py create mode 100644 tests/test_release_notes.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 644a501..c576a67 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -142,6 +142,12 @@ jobs: --output "${asset}.asc" "$asset" done + - name: Extract release notes from the changelog + shell: bash + run: | + set -euo pipefail + python scripts/release_notes.py "${GITHUB_REF_NAME#v}" > "${RUNNER_TEMP}/release-notes.md" + - name: Stage draft release with assets env: GH_TOKEN: ${{ github.token }} @@ -156,13 +162,16 @@ jobs: fi gh release upload "${GITHUB_REF_NAME}" release/* \ --repo "${GITHUB_REPOSITORY}" --clobber + gh release edit "${GITHUB_REF_NAME}" \ + --repo "${GITHUB_REPOSITORY}" \ + --notes-file "${RUNNER_TEMP}/release-notes.md" else gh release create "${GITHUB_REF_NAME}" release/* \ --repo "${GITHUB_REPOSITORY}" \ --draft \ --verify-tag \ --title "TrinaxAI ${GITHUB_REF_NAME#v}" \ - --generate-notes + --notes-file "${RUNNER_TEMP}/release-notes.md" fi - name: Verify exact draft release assets and signatures diff --git a/README.es.md b/README.es.md index c224371..33e8072 100644 --- a/README.es.md +++ b/README.es.md @@ -125,6 +125,16 @@ La configuración elige un perfil según la memoria y los recursos gráficos: El perfil `8gb` funciona solo con CPU. Consulta la [referencia de configuración](docs/CONFIGURATION.es.md) para modelos y recursos. +## Límites conocidos + +- Preguntas sobre código respondidas por modelos locales pequeños: las fuentes + citadas a veces son erróneas o incompletas, así que abre el archivo citado + antes de fiarte de una respuesta. +- `trinaxai research` es lento en un equipo sin GPU. +- No medido: el flujo completo (instalación, chat, RAG, agente y app web) en + Windows, con GPU y con modelos grandes. macOS y Windows están cubiertos por las + comprobaciones automáticas de CI, no por ejecuciones de extremo a extremo. + ## Privacidad y seguridad TrinaxAI enlaza los servicios locales a loopback por defecto. Ollama no se diff --git a/README.md b/README.md index 9366cd3..3900479 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,16 @@ Setup chooses a model profile from available memory and GPU resources: The `8gb` profile works with CPU-only hardware. See the [configuration reference](docs/CONFIGURATION.md) for model and resource settings. +## Known limits + +- Questions about code answered by small local models: the cited sources are + sometimes wrong or incomplete, so open the cited file before relying on an + answer. +- `trinaxai research` is slow on a CPU-only computer. +- Not measured: the full flow (install, chat, RAG, agent, web app) on Windows, + on a GPU, and with large models. macOS and Windows are covered by the automated + CI checks, not by end-to-end runs. + ## Privacy and security TrinaxAI binds local services to loopback by default. Ollama is not exposed as diff --git a/docs/CHANGELOG.es.md b/docs/CHANGELOG.es.md index 2169838..2b9b8c8 100644 --- a/docs/CHANGELOG.es.md +++ b/docs/CHANGELOG.es.md @@ -18,7 +18,7 @@ el formato de [Keep a Changelog](https://keepachangelog.com/). ## [Sin publicar] -## [1.4.0] — 2026-10-23 +## [1.4.0] — 2026-10-26 ### Añadido @@ -326,6 +326,16 @@ el formato de [Keep a Changelog](https://keepachangelog.com/). traducidos, y una instalación fallida indica que se puede ejecutar de nuevo sin riesgo. +### Límites conocidos + +- Preguntas sobre código respondidas por modelos locales pequeños: las fuentes + citadas a veces son erróneas o incompletas, así que abre el archivo citado + antes de fiarte de una respuesta. +- `trinaxai research` es lento en un equipo sin GPU. +- No medido: el flujo completo (instalación, chat, RAG, agente y app web) en + Windows, con GPU y con modelos grandes. macOS y Windows están cubiertos por las + comprobaciones automáticas de CI, no por ejecuciones de extremo a extremo. + ## [1.3.0] — 2026-10-18 ### Cambiado diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d92db74..548aa54 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -18,7 +18,7 @@ All notable changes to TrinaxAI are documented here. This project follows the ## [Unreleased] -## [1.4.0] — 2026-10-23 +## [1.4.0] — 2026-10-26 ### Added @@ -311,6 +311,16 @@ All notable changes to TrinaxAI are documented here. This project follows the - Installer messages that appeared in English in Spanish mode are translated, and a failed install says it is safe to run again. +### Known limits + +- Questions about code answered by small local models: the cited sources are + sometimes wrong or incomplete, so open the cited file before relying on an + answer. +- `trinaxai research` is slow on a CPU-only computer. +- Not measured: the full flow (install, chat, RAG, agent, web app) on Windows, + on a GPU, and with large models. macOS and Windows are covered by the automated + CI checks, not by end-to-end runs. + ## [1.3.0] — 2026-10-18 ### Changed diff --git a/scripts/release_notes.py b/scripts/release_notes.py new file mode 100644 index 0000000..a266f0b --- /dev/null +++ b/scripts/release_notes.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Print one release's section of docs/CHANGELOG.md, to use as the GitHub release notes. + +The release workflow fails when the section is missing or empty, so a tag can never +publish notes that skip the known limits written in the changelog. +""" + +from __future__ import annotations + +import argparse +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +DEFAULT_CHANGELOG = ROOT / "docs" / "CHANGELOG.md" + + +def extract_release_notes(changelog: str, version: str) -> str: + """Return the body under ``## [version]`` up to the next ``## `` heading.""" + heading = re.compile(rf"^## \[{re.escape(version)}\][^\n]*(?:\n|$)", re.MULTILINE) + start = heading.search(changelog) + if start is None: + raise ValueError(f"CHANGELOG has no section for version {version}") + rest = changelog[start.end() :] + following = re.search(r"^## ", rest, re.MULTILINE) + body = (rest[: following.start()] if following else rest).strip() + if not body: + raise ValueError(f"CHANGELOG section for version {version} is empty") + return body + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("version", help="release version without the leading v, for example 1.4.0") + parser.add_argument("--changelog", type=Path, default=DEFAULT_CHANGELOG) + args = parser.parse_args(argv) + try: + notes = extract_release_notes(args.changelog.read_text(encoding="utf-8"), args.version) + except (OSError, ValueError) as exc: + print(f"release notes: {exc}", file=sys.stderr) + return 1 + print(notes) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_release_notes.py b/tests/test_release_notes.py new file mode 100644 index 0000000..174be3a --- /dev/null +++ b/tests/test_release_notes.py @@ -0,0 +1,69 @@ +import re +from pathlib import Path + +import pytest + +from scripts import release_notes + +CHANGELOG = """# Changelog + +## [Unreleased] + +## [1.4.0] — 2026-10-26 + +### Added + +- Something new. + +### Known limits + +- A limit. + +## [1.3.0] — 2026-10-18 + +- Older. +""" + + +def test_extracts_only_the_requested_section() -> None: + notes = release_notes.extract_release_notes(CHANGELOG, "1.4.0") + + assert notes.startswith("### Added") + assert "### Known limits" in notes + assert "Older." not in notes + assert "[1.4.0]" not in notes + + +def test_last_section_runs_to_the_end_of_the_file() -> None: + assert release_notes.extract_release_notes(CHANGELOG, "1.3.0") == "- Older." + + +def test_missing_or_empty_sections_are_errors() -> None: + with pytest.raises(ValueError, match="no section for version 9.9.9"): + release_notes.extract_release_notes(CHANGELOG, "9.9.9") + with pytest.raises(ValueError, match="empty"): + release_notes.extract_release_notes(CHANGELOG, "Unreleased") + with pytest.raises(ValueError, match="no section"): + release_notes.extract_release_notes(CHANGELOG, "1.4") + + +def test_cli_prints_notes_and_fails_closed(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: + changelog = tmp_path / "CHANGELOG.md" + changelog.write_text(CHANGELOG, encoding="utf-8") + + assert release_notes.main(["1.4.0", "--changelog", str(changelog)]) == 0 + assert "### Known limits" in capsys.readouterr().out + assert release_notes.main(["2.0.0", "--changelog", str(changelog)]) == 1 + assert "no section for version 2.0.0" in capsys.readouterr().err + assert release_notes.main(["1.4.0", "--changelog", str(tmp_path / "missing.md")]) == 1 + + +def test_the_repository_changelog_has_notes_for_the_current_version() -> None: + root = Path(release_notes.__file__).resolve().parents[1] + match = re.search(r'^version = "([^"]+)"$', (root / "pyproject.toml").read_text(encoding="utf-8"), re.MULTILINE) + assert match is not None + version = match.group(1) + + notes = release_notes.extract_release_notes((root / "docs" / "CHANGELOG.md").read_text(encoding="utf-8"), version) + + assert notes diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 07ad785..90d7a3f 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -590,7 +590,9 @@ def test_tagged_releases_publish_a_simple_verified_release() -> None: assert "SHA256SUMS" in workflow assert "gh release create" in workflow assert "--verify-tag" in workflow - assert "--generate-notes" in workflow + assert "--generate-notes" not in workflow + assert "scripts/release_notes.py" in workflow + assert workflow.count("--notes-file") == 2 assert "docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e" in workflow assert "actions/attest@v4" not in workflow