diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml index 9980e0f2..c0b13874 100644 --- a/.github/workflows/release-stable.yml +++ b/.github/workflows/release-stable.yml @@ -4,6 +4,7 @@ on: push: tags: - 'stable-v*' + - 'v20*' env: # Bump this when Tauri/Rust target artifacts capture stale absolute paths. @@ -34,14 +35,24 @@ jobs: from datetime import date tag = os.environ["GITHUB_REF_NAME"] - version = tag.removeprefix("stable-v") - match = re.fullmatch(r"(\d{4})\.(\d{1,2})\.(\d{1,2})", version) - if not match: - raise SystemExit(f"Stable tags must use stable-vYYYY.M.D, got {tag}") + legacy_match = re.fullmatch(r"stable-v(\d{4})\.(\d{1,2})\.(\d{1,2})", tag) + date_match = re.fullmatch(r"v(\d{4})-(\d{2})-(\d{2})", tag) + + if date_match: + year, month, day = map(int, date_match.groups()) + date(year, month, day) + version = f"{year}.{month}.{day}" + display_version = tag + elif legacy_match: + year, month, day = map(int, legacy_match.groups()) + date(year, month, day) + version = f"{year}.{month}.{day}" + display_version = version + else: + raise SystemExit(f"Stable tags must use vYYYY-MM-DD or stable-vYYYY.M.D, got {tag}") - date(*map(int, match.groups())) print(f"version={version}") - print(f"display_version={version}") + print(f"display_version={display_version}") print(f"tag={tag}") PY @@ -565,16 +576,23 @@ jobs: - name: Generate release notes run: | - PREV_TAG=$(git tag --list 'stable-v*' --sort=-version:refname | grep -vx "${{ needs.version.outputs.tag }}" | head -n 1 || echo "") - if [ -z "$PREV_TAG" ]; then - NOTES=$(git log --oneline --no-merges -20) + NOTES_FILE="release-notes/${{ needs.version.outputs.tag }}.md" + if [ -f "$NOTES_FILE" ]; then + cat "$NOTES_FILE" > release_notes.md else - NOTES=$(git log --oneline --no-merges "${PREV_TAG}..${{ needs.version.outputs.tag }}") + PREV_TAG=$(git for-each-ref --sort=-creatordate --format='%(refname:short)' refs/tags/v20* refs/tags/stable-v* | grep -vx "${{ needs.version.outputs.tag }}" | head -n 1 || echo "") + if [ -z "$PREV_TAG" ]; then + NOTES=$(git log --oneline --no-merges -20) + else + NOTES=$(git log --oneline --no-merges "${PREV_TAG}..${{ needs.version.outputs.tag }}") + fi + { + echo "## What's Changed" + echo "" + echo "$NOTES" | while IFS= read -r line; do echo "- $line"; done + } > release_notes.md fi { - echo "## What's Changed" - echo "" - echo "$NOTES" | while IFS= read -r line; do echo "- $line"; done echo "" echo "---" echo "**Stable release — manually promoted from \`main\`**" @@ -582,7 +600,7 @@ jobs: echo "**Includes macOS (Apple Silicon and Intel), Windows x64, and Linux x64 bundles**" echo "" echo "*Built from \`$(git rev-parse --short ${{ needs.version.outputs.tag }})\` on $(date -u +%Y-%m-%d)*" - } > release_notes.md + } >> release_notes.md - name: Build stable-latest.json run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b1abf9cc..5d390960 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,10 +69,18 @@ jobs: else: today = datetime.now(timezone.utc).date() stable_date = None - stable_pattern = re.compile(r"^stable-v(\d{4})\.(\d{1,2})\.(\d{1,2})$") + stable_patterns = ( + re.compile(r"^v(\d{4})-(\d{2})-(\d{2})$"), + re.compile(r"^stable-v(\d{4})\.(\d{1,2})\.(\d{1,2})$"), + ) - for stable_tag in lines(["git", "tag", "--list", "stable-v*", "--sort=-version:refname"]): - match = stable_pattern.fullmatch(stable_tag) + stable_tags = lines([ + "git", "for-each-ref", "--sort=-creatordate", "--format=%(refname:short)", + "refs/tags/v20*", "refs/tags/stable-v*", + ]) + + for stable_tag in stable_tags: + match = next((pattern.fullmatch(stable_tag) for pattern in stable_patterns if pattern.fullmatch(stable_tag)), None) if not match: continue diff --git a/release-notes/v2026-05-04.md b/release-notes/v2026-05-04.md new file mode 100644 index 00000000..bfa633e1 --- /dev/null +++ b/release-notes/v2026-05-04.md @@ -0,0 +1,20 @@ +## New Features + +- 🤖 **Direct AI Model Providers** — Use OpenAI, Anthropic, Gemini, OpenRouter, Ollama, LM Studio, or a custom OpenAI-compatible endpoint directly from Tolaria. +- 🖊️ **Markdown Whiteboards** — Create and edit tldraw-powered whiteboards that live as durable Markdown files in your vault. +- 🧭 **Table of Contents Panel** — Navigate long notes with a lazy, outline-style panel generated from the current document headings. +- 📄 **Readable Release Notes** — View stable releases through curated notes written for users instead of raw commit lists. + +## Improvements + +- 🧩 **Cleaner AI Settings** — Configure provider secrets, local models, and AI targets through a more focused settings experience. +- 💬 **Better Agent Context Handling** — Large AI agent contexts are compacted more safely, and Codex MCP tools are exposed more reliably. +- 🧱 **Improved Editor Blocks** — Code blocks can be copied more easily, block controls feel steadier, and rich exports avoid unsupported browser APIs. +- 🗂️ **Smarter Note and Type Handling** — Renames, type changes, frontmatter placeholders, and path identity now behave more consistently across vault flows. +- 🌍 **Better International Editing** — RTL text direction, IME composition, Korean sidebar copy, and unicode git paths all received focused polish. + +## Stability and Fixes + +- Embedded diagrams, tldraw whiteboard assets, stale checklist toggles, and stale note open or rename flows were hardened to avoid broken editor states. +- Vault recovery, missing active vault handling, fresh-note heading paste, and same-path type collisions now fail more gracefully. +- Linux AppImage startup, MCP resource discovery, release CI, Codacy security findings, and AI provider runtime paths all received stability fixes.