release: cut v1.0.0
Prepare the first public 1.0.0 release and finish the remaining CI hardening work. Highlights: - align Python, Rust, WASM, Conda, API, MCP, and docs version metadata to 1.0.0 - promote package metadata to Production/Stable and update stability/versioning docs for the stable series - move the accumulated Unreleased notes into a dated 1.0.0 changelog section and keep a fresh top-level Unreleased block - strengthen the changelog checker so it validates a single top-level Unreleased section - fix the CI/package support mismatch by declaring Python >=3.10 consistently and gating pandas-ta extras to Python 3.12+ - restore Sphinx autodoc compatibility for documented ferro_ta.<module> imports by registering module aliases - make the TA-Lib benchmark guardrail less flaky by checking median and tail-percentile speedups instead of failing on a single mild outlier - switch PyPI publishing to OIDC-only trusted publishing and wire the changelog check into the required CI gate - apply the Ruff-driven cleanup across the Python and test tree and refresh uv/cargo lockfiles Validated locally: - python3 scripts/check_changelog.py - uv run --with ruff ruff check python tests - uv run --with ruff ruff format --check python tests - uv lock --check - sphinx-build -b html docs docs/_build -W --keep-going - build/install the ferro_ta 1.0.0 wheel successfully
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate that CHANGELOG.md keeps a single top-level [Unreleased] section."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main() -> int:
|
||||
changelog = Path("CHANGELOG.md")
|
||||
if not changelog.exists():
|
||||
print("ERROR: CHANGELOG.md not found.")
|
||||
return 1
|
||||
|
||||
text = changelog.read_text(encoding="utf-8")
|
||||
headings = list(re.finditer(r"^## \[(.+?)\]\s*$", text, flags=re.MULTILINE))
|
||||
unreleased = [m for m in headings if m.group(1) == "Unreleased"]
|
||||
|
||||
if not unreleased:
|
||||
print("ERROR: CHANGELOG.md is missing a '## [Unreleased]' heading.")
|
||||
return 1
|
||||
if len(unreleased) > 1:
|
||||
print("ERROR: CHANGELOG.md contains multiple '## [Unreleased]' headings.")
|
||||
return 1
|
||||
|
||||
if headings and headings[0].group(1) != "Unreleased":
|
||||
print("ERROR: '## [Unreleased]' must be the first top-level changelog section.")
|
||||
return 1
|
||||
|
||||
print("OK: CHANGELOG.md contains a single top-level [Unreleased] section.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user