Skip to content

Add website release notes with AI-powered generation pipeline#3763

Merged
mattleibow merged 38 commits into
mainfrom
mattleibow/website-release-notes
Apr 28, 2026
Merged

Add website release notes with AI-powered generation pipeline#3763
mattleibow merged 38 commits into
mainfrom
mattleibow/website-release-notes

Conversation

@mattleibow

@mattleibow mattleibow commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a complete release notes section to the SkiaSharp website with an AI-powered pipeline for generating and maintaining polished version pages.

76 files changed, 6,081 insertions

What's Included

Release Notes Pages (63 versions)

  • One polished page per base version in documentation/docfx/releases/
  • Covers all versions from 1.49.0 (2016) through 4.133.0 (upcoming)
  • Each page follows a consistent template: highlights, categorized features, security/bug fixes, platform support table, community contributors, and preview sections

release-notes Skill

  • New skill at .agents/skills/release-notes/ for generating and regenerating release notes
  • Includes generate-release-notes.py script with 4 commands:
    • --version X.Y.Z — fetch raw GitHub release data for a specific version
    • --last N — fetch the N most recent versions
    • --unreleased — fetch unreleased PRs via git commit ancestry (not dates)
    • --update-toc — regenerate TOC.yml, index.md, and create upcoming version file
  • Baseline tag detection uses semver comparison to handle release branches correctly

update-release-notes Agentic Workflow

  • Triggers on every push to main
  • Fetches unreleased PRs, reads the template, AI-polishes into categorized notes
  • Writes the upcoming version file (e.g., 4.133.0.md) and creates a PR
  • Self-bootstrapping: creates the version file if it doesn't exist yet

Template (TEMPLATE.md)

  • Real example page (3.119.2) with inline HTML comments as formatting tips
  • One template for all statuses: stable, preview-only, and upcoming
  • AI adapts the template based on version status

Website Integration

  • "Release Notes" tab in DocFX sidebar navigation
  • "Release Notes" link in landing page header
  • Release Notes card in homepage resources section
  • TOC groups versions by major.minor.x with "Obsolete Versions" node for 1.x/2.x
  • Upcoming version shows (Upcoming) label, reads version from azure-templates-variables.yml

Skill Updates

  • release-publish Step 7 now invokes the release-notes skill instead of inlining instructions
  • AGENTS.md updated with release notes commands and directory guide

Architecture

Push to main
  → update-release-notes agentic workflow
    → generate-release-notes.py --unreleased (git ancestry)
    → AI polishes using TEMPLATE.md
    → Writes {version}.md, creates PR

Release published
  → release-publish skill Step 7
    → invokes release-notes skill
      → generate-release-notes.py --version X.Y.Z
      → AI polishes using TEMPLATE.md
      → Writes {version}.md
    → Commits to release branch

Manual regeneration
  → "regenerate release notes for 3.119.x"
    → release-notes skill
      → Fetches raw data, reads template, writes polished pages

mattleibow and others added 14 commits April 27, 2026 20:42
- Add generator script (scripts/generate-release-notes.py) that fetches
  all GitHub release bodies and generates DocFX-compatible markdown files
  grouped by base version (stable + previews together)
- Add unreleased notes generator (scripts/generate-unreleased-notes.py)
  that populates 'What's Coming Next' from merged PRs since last release
- Backfill all 144 historical release notes (62 base versions) into
  documentation/docfx/releases/
- Add 'Release Notes' tab to DocFX navigation and landing page header
- Wire unreleased generation into the build-site CI workflow
- Update release-publish skill with new Step 7 to regenerate website
  release notes after annotating GitHub releases
- Add .gitignore exception for documentation/docfx/releases/

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add TEMPLATE.md defining the mixed style (highlights summary + categorized
  features + platform table + community contributors + minimal preview sections)
- Refactor generate-release-notes.py as a data fetcher with flexible params:
  --version X.Y.Z, --last N, --all, --update-toc
- Default mode outputs raw data to a temp dir for AI to reformat using the template
- Exclude TEMPLATE.md from DocFX build output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create a gh-aw workflow that triggers on push to main and regenerates
the 'What's Coming Next' section in the release notes index page.

The workflow:
- Runs scripts/generate-unreleased-notes.py to fetch merged PRs
- Uses AI to polish raw PR data into the TEMPLATE.md format style
- Creates a PR with the updated documentation/docfx/releases/index.md
- Uses paths-ignore to prevent infinite trigger loops

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The agentic workflow (update-release-notes.md) now handles this by
committing AI-polished content to the repo on every merge to main.
The build-site step would overwrite that polished content with raw
mechanical output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactor generate-unreleased-notes.py to output to stdout/file instead
of modifying index.md in place. The agentic workflow now reads from a
temp file — no more modify-read-revert gymnastics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…preview.1.1

Summarizes 18 merged PRs into categorized release notes including:
- Variable font support and color font palettes
- SKSamplingOptions for surface drawing
- Default typeface resolution fix
- Debian 13 Docker build fix
- Uno Platform WebAssembly gallery sample

Community contributions by @ramezgerges credited with ❤️.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the UNRELEASED_PLACEHOLDER + magic italic line with a clear
BEGIN/END fence pair. Easier to understand and more robust for the
agentic workflow to locate and replace.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Transforms the raw GitHub release data into the structured template with:
- Highlights section leading with security hardening theme
- Categorized security changes (Spectre, CFG, BufferSecurityCheck)
- New features section for tvOS SKSurface.Create overloads
- Platform support table
- Community contributors table (3 contributors)
- Minimal preview sections with one-line summaries
- Internal/CI PRs omitted per template rules

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reformat raw GitHub release data into the polished docfx release notes
template with categorized features, bug fixes, platform support table,
and community contributor credits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AI-polished release notes for the 5 most recent base versions:
- 3.119.0: Major feature release (Skia m119, D3D, tvOS Metal, new archs)
- 3.119.1: Bugfix/maintenance (Metal init, WinUI, PDF, zlib update)
- 3.119.2: Security hardening (Spectre, CFG, BufferSecurityCheck)
- 3.119.3: Security deps + stability (libpng, expat, brotli, webp, AoT fix)
- 3.119.4: Platform expansion (GTK4, Bionic, Tizen, D3D12, samples)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AI-polished release notes for all historical versions:
- 1.49.x (6 versions): Initial releases through tvOS + PDF support
- 1.53.x (5 versions): Codec, strong naming, GPU rendering
- 1.54.x–1.56.x (7 versions): GPU backend, SVG, .NET Standard
- 1.57.x–1.58.x (5 versions): Skia m56–m58, HarfBuzz, touch events
- 1.59.x (5 versions): Skia m59, Unity3D, SK3dView
- 1.60.x–1.68.x (10 versions): Skia m60–m68, GPU rewrite, text shaping
- 2.80.x (5 versions): Skia m80, Vulkan, ARM, WASM, Metal
- 2.88.x (10 versions): .NET 6–9, MAUI, Blazor, Skottie
- 3.0.0–3.118.0 (4 versions): Major v3 overhaul, Skia m116–m118

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update release-publish Step 7 with AI reformat workflow (fetch raw →
  read template → AI polish → write → update TOC → commit)
- Add release notes directories to AGENTS.md directory guide
- Add release notes commands to AGENTS.md command table

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

📦 Try the packages from this PR

Warning

Do not run these scripts without first reviewing the code in this PR.

Step 1 — Download the packages

bash / macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.sh | bash -s -- 3763

PowerShell / Windows:

iex "& { $(irm https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.ps1) } 3763"

Step 2 — Add the local NuGet source

dotnet nuget add source ~/.skiasharp/hives/pr-3763/packages --name skiasharp-pr-3763
More options
Option Description
--successful-only / -SuccessfulOnly Only use successful builds
--force / -Force Overwrite previously downloaded packages
--list / -List List available artifacts without downloading
--build-id ID / -BuildId ID Download from a specific build

Or download manually from Azure Pipelines — look for the nuget artifact on the build for this PR.

Remove the source when you're done:

dotnet nuget remove source skiasharp-pr-3763

@github-actions

github-actions Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

📖 Documentation Preview

The documentation for this PR has been deployed and is available at:

🔗 View Staging Site
🔗 View Staging Docs
🔗 View Staging Gallery (Blazor)
🔗 View Staging Gallery (Uno Platform)

This preview will be updated automatically when you push new commits to this PR.


This comment is automatically updated by the documentation staging workflow.

mattleibow and others added 5 commits April 28, 2026 01:02
…rsion

- Group TOC and index by major.minor.x (e.g., Version 3.119.x)
- Mark 1.x and 2.x as Obsolete in the index
- Add GitHub Release link to the blockquote header on every version page
- Fix preview-only versions to show 'Preview only' instead of 'Released'
- Use SKIASHARP_VERSION from azure-templates-variables.yml for the
  upcoming version heading (currently 4.133.0)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create 4.133.0.md as a real version file with UNRELEASED_BEGIN/END
  fences (read from SKIASHARP_VERSION in azure-templates-variables.yml)
- Agentic workflow now updates the version file, not index.md
- TOC groups show (Obsolete) for 1.x and 2.x
- Index is just a clean version list with (Upcoming) label
- Remove UNRELEASED fences from index.md entirely

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- 1.x and 2.x sections use <details>/<summary> for collapsible display
- 4.133.0 treated as a real version in TOC and index (groups under
  4.133.x when more versions exist)
- Update TEMPLATE.md with upcoming version workflow docs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Single-member groups (3.118.0, 3.0.0, 4.133.0) now get the same
Version X.Y.x heading as multi-member groups, both in TOC.yml and
index.md. Consistent structure everywhere.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Single-member groups now also get items: with their version listed
underneath, matching multi-member groups.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mattleibow and others added 6 commits April 28, 2026 01:57
- Remove <details>/<summary> from index.md — DocFX doesn't render them
- Populate 4.133.0.md with AI-polished unreleased notes (variable fonts,
  color palettes, SKSamplingOptions, Uno Platform samples)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move all 1.x and 2.x versions under an 'Obsolete Versions' parent
node in the sidebar TOC. Remove (Obsolete) noise from individual
version names and index headings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add Skia milestone 133 engine update as headline feature
- Link all @username mentions as [@user](https://github.com/user)
- Update TEMPLATE.md to require linked usernames in prose
- Remove copilot-swe-agent ❤️ (bot, not community contributor)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Root causes of the two 4.133.0 issues:
- Skia bump missing: raw data only has PRs since last tag, but the
  Skia bump was IN that tag. Added rule to infer Skia milestone from
  the version number (4.133.0 → m133) and include it as a feature.
- Bare @username: template and workflow now explicitly require linked
  usernames everywhere: [@user](https://github.com/user)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Skia m133 bump (PR #3702) is still open — incorrectly added it
to 4.133.0.md by inferring from the version number. Now the workflow
only mentions Skia bumps when a 'Bump skia' PR appears in the merged
PR list.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Skia m133 bump (PR #3660) was already merged — it's the defining
feature of this version. The workflow now always mentions the Skia
engine version (derived from the version number) and searches for the
corresponding merged bump PR to link to.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mattleibow and others added 13 commits April 28, 2026 02:17
The date-based approach (merged:>release_date) missed PRs that were
merged before the release date but after the release commit. This
happened because the release tag can be cut from an earlier commit
on main, leaving newer-merged PRs unreleased.

Now uses git log {tag}..origin/main to find commits not in the tag,
extracts PR numbers from merge commit messages, and fetches their
details. This correctly found 57 PRs (vs 20 with the date approach),
including the Skia m133 bump (PR #3660).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When SKIASHARP_VERSION changes (e.g., bumped to 5.0.0), the version
file won't exist yet. Step 1 now runs --update-toc to create the file
with fence markers and update the TOC/index before polishing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explain when and why to run --update-toc, what it does, and that
TOC.yml and index.md should never be edited manually.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TEMPLATE.md is now a pure example file — a real polished release notes
page (3.119.2) with inline HTML comments as tips. No workflow docs, no
duplicated instructions. AI reads it as a style reference.

Agentic workflow rewritten to be self-contained:
- Step 1: ensure version file exists (creates via --update-toc if not)
- Step 2: fetch raw data via commit ancestry
- Step 3: read template as style reference
- Step 4: polish with clear rules (Skia detection, linked names, etc.)
- Step 5: write into UNRELEASED fences

release-publish skill Step 7 simplified to point at the template
instead of duplicating formatting instructions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The workflow rewrites the entire file each run — no need for fence
markers to locate a replacement section. Simpler and cleaner.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merged generate-release-notes.py and generate-unreleased-notes.py into
one script with clear subcommands:
  --version X.Y.Z    Fetch raw released version data
  --last N           Fetch N most recent versions
  --unreleased       Fetch unreleased PRs via git ancestry
  --update-toc       Regenerate TOC + index + upcoming file

Removed all duplicated logic:
- No more emoji/classification in the script (AI does that)
- No more date-based filtering (uses commit ancestry)
- No more fragile relative path construction
- Clean separation: script collects data, AI formats it

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Release tags live on release/* branches, not main. Use semver to find
the highest tag <= the upcoming version, then fetch it for git log.
The diff works because release branches fork from main.

Handles the scenario: v4 preview tagged, then v3 hotfix tagged later.
The baseline for v4 unreleased is still the v4 preview (or the latest
v3 if no v4 tags exist yet).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generated entirely by the agentic workflow prompt with zero manual
intervention. File created from scratch, 58 PRs processed, Skia m132/m133
detected, v3→v4 breaking change found, 3 community contributors linked.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
New skill at .agents/skills/release-notes/ handles generating and
regenerating polished website release notes for any version. Supports
single versions, multiple versions, and parallel processing.

release-publish Step 7 now just invokes the release-notes skill
instead of inlining the entire formatting workflow.

Removed REGEN-PROMPT.md (replaced by the skill).
Deleted 3.119.x files for clean regeneration test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- All 5 versions regenerated from scratch by the skill
- Skill no longer commits — that's release-publish's job
- TOC and index updated

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Script now lives at .agents/skills/release-notes/scripts/ alongside
the skill that uses it. All references updated: AGENTS.md, the
agentic workflow, and the skill SKILL.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mattleibow mattleibow changed the title Add release notes section to the website Add website release notes with AI-powered generation pipeline Apr 28, 2026
@mattleibow
mattleibow merged commit 1093ab6 into main Apr 28, 2026
5 of 6 checks passed
@mattleibow
mattleibow deleted the mattleibow/website-release-notes branch April 28, 2026 02:39
github-actions Bot pushed a commit that referenced this pull request Apr 28, 2026
mattleibow added a commit that referenced this pull request Jun 17, 2026
…lup (R1/R2/R3)

The versions.json supersession migration (#4171/#4174) correctly made
"which version supersedes which" deterministic via versions.json, but its
move from per-push branch runs to a bulk `--all` pass silently regressed
three documented behaviours. Pages were migrated in #4174 without the
script emitting the data those pages used to contain, so the features were
dropped on the next regeneration instead of failing loudly.

Three regressions, each restored from a deterministic source (not heuristics):

R1 — in-flight naming. 4.148 and 4.150 were written as terminal
`{version}.md` and the cleanup pass then deleted the real
`{version}-unreleased.md`. Root cause: `--all` picks the rc.1/preview.1
branch as canonical for the version. Fixed with a terminal-vs-in-flight
rule in `_page_filename` (suffix-less `release/X.Y.Z` branch exists, or
`status: superseded` in versions.json => `{version}.md`; otherwise
`{version}-unreleased.md`) plus an ownership filter in `cmd_all` so the
line head (main / `release/X.Y.x`) owns the `-unreleased` page and the
matching rc/preview branch is deferred instead of colliding.

R2 — in-flight `.x` rollup was a servicing-delta instead of the full
cumulative rollup. `determine_diff_range` now honors the versions.json
`compare_to` first (4.148.0 -> 3.119.4) and only does a servicing delta
once the `.0` has actually shipped a stable tag.

R3 — the trailing `## Preview N (date)` sections were lost. The original
3.119.2.md (#3763) and TEMPLATE.md have them and SKILL rules 9/10 mandate
them, but #4174 deleted them on regen because the script never emitted
preview data. `collect_preview_milestones` now enumerates them from the
published prerelease git tags within the page's diff range (deduped to the
latest build per milestone, dated, with chained compare links). A page
rolls up a skipped predecessor minor's previews too, so the 4.148 page
lists the 4.147 previews that match its rolled-up PRs.

Two separate deterministic sources, no magic: versions.json answers "which
version supersedes which"; published tags answer "which previews shipped
and when". Documented in code comments (R1/R2/R3) and a new SKILL.md
"Page naming & preview rollup" section so this can't silently regress on
the next migration. Validated with an offline `--all` dry-run: correct
`-unreleased` filenames, 4.148 rolls up 4.147 p1/p2/p3 + rc1, no bare
4.148.0.md/4.150.0.md, 3.119.x unchanged, and the 3.119.2 compare links
reproduce the original page exactly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mattleibow added a commit that referenced this pull request Jun 17, 2026
…lup (R1/R2/R3) (#4179)

release-notes: restore in-flight -unreleased naming + per-preview rollup (R1/R2/R3) (#4179)

The versions.json supersession migration (#4171/#4174) correctly made
"which version supersedes which" deterministic via versions.json, but its
move from per-push branch runs to a bulk `--all` pass silently regressed
three documented behaviours. #4174 migrated the pages without the script
emitting the data those pages used to contain, so the features were dropped
on the next regeneration instead of failing loudly.

Three regressions, each restored from a deterministic source (not heuristics):

R1 — in-flight naming. 4.148 and 4.150 were written as terminal
`{version}.md` and the cleanup pass then deleted the real
`{version}-unreleased.md`. Root cause: `--all` picks the rc.1/preview.1
branch as canonical for the version. Fixed with a terminal-vs-in-flight
rule in `_page_filename` (a suffix-less `release/X.Y.Z` branch exists, or
`status: superseded` in versions.json => `{version}.md`; otherwise
`{version}-unreleased.md`) plus an ownership filter in `cmd_all` so the
line head (main / `release/X.Y.x`) owns the `-unreleased` page and the
matching rc/preview branch is deferred instead of colliding.

R2 — in-flight `.x` rollup was a servicing delta instead of the full
cumulative rollup. `determine_diff_range` now honors the versions.json
`compare_to` first (4.148.0 -> 3.119.4) and only does a servicing delta
once the `.0` has actually shipped a stable tag.

R3 — the trailing `## Preview N (date)` sections were lost. The original
3.119.2.md (#3763) and TEMPLATE.md have them and SKILL rules 9/10 mandate
them, but #4174 deleted them on regen because the script never emitted
preview data. `collect_preview_milestones` now enumerates them from the
published prerelease git tags within the page's diff range (deduped to the
latest build per milestone, dated, with chained compare links). A page
rolls up a skipped predecessor minor's previews too, so the 4.148 page
lists the 4.147 previews that match its rolled-up PRs.

Two separate deterministic sources, no magic: versions.json answers "which
version supersedes which"; published tags answer "which previews shipped
and when". Documented in code comments (R1/R2/R3) and a new SKILL.md
"Page naming & preview rollup" section so this can't silently regress on
the next migration. Validated with an offline `--all` dry-run: correct
`-unreleased` filenames, 4.148 rolls up 4.147 p1/p2/p3 + rc1, no bare
4.148.0.md/4.150.0.md, 3.119.x unchanged, and the 3.119.2 compare links
reproduce the original page exactly.

Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant