diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0f35ee3..fd32e00 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -62,6 +62,29 @@ jobs: fi echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" + # Release notes come from CHANGELOG.md. A stable release must have its own dated section; + # a prerelease uses its section if present, otherwise the Unreleased section. + - name: Extract release notes from CHANGELOG.md + run: | + VERSION="${GITHUB_REF_NAME#v}" + if eng/changelog-section.sh "$VERSION" > release-notes.md; then + echo "Using the [$VERSION] section of CHANGELOG.md" + elif [[ "$VERSION" == *-* ]]; then + eng/changelog-section.sh Unreleased > release-notes.md + echo "Prerelease: using the [Unreleased] section of CHANGELOG.md" + else + echo "::error::CHANGELOG.md needs a '## [$VERSION] - ' section before $VERSION can be released." + exit 1 + fi + printf '\n**Full changelog:** https://github.com/%s/blob/%s/CHANGELOG.md\n' "$GITHUB_REPOSITORY" "$GITHUB_REF_NAME" >> release-notes.md + + - name: Upload release notes + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: release-notes + path: release-notes.md + if-no-files-found: error + # ───────────────────────────────────────────────────────────────────────────── # 2. Pack KumikoUI.Core and KumikoUI.SkiaSharp (plain net10.0 — Linux is fine) # ───────────────────────────────────────────────────────────────────────────── @@ -314,13 +337,19 @@ jobs: done # ── GitHub Release ───────────────────────────────────────────────────── + - name: Download release notes + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: release-notes + path: notes + + # Runs for tag pushes and for manual runs against a tag (the only refs resolve-version accepts). - name: Create GitHub Release uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') with: tag_name: ${{ github.ref_name }} name: ${{ github.ref_name }} + body_path: notes/release-notes.md draft: false prerelease: ${{ contains(github.ref_name, '-') }} - generate_release_notes: true files: publish/*.nupkg diff --git a/CHANGELOG.md b/CHANGELOG.md index b87b7ba..36f58fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,78 @@ # Changelog -All notable changes to this project are documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +All notable changes to KumikoUI are documented in this file. All four packages (KumikoUI.Core, KumikoUI.SkiaSharp, KumikoUI.Maui, KumikoUI.Uno) share one version. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) as described in [docs/VERSIONING.md](docs/VERSIONING.md). Each release's section is also used as its GitHub release notes. ## [Unreleased] +### Added +- **KumikoUI.Uno**: a new package hosting the grid on the Uno Platform (Windows App SDK, desktop on Windows/macOS/Linux, WebAssembly, Android, iOS) with the same engine, rendering and features as KumikoUI.Maui, plus `KumikoFonts` for registering custom fonts from app assets, and the `SampleApp.Uno` sample. +- `DataGridStyle.PinBottomSummaryRows` (default `true`): `Position=Bottom` table summary rows are pinned to the bottom of the viewport as a fixed footer instead of scrolling after the last row. **Behaviour change** for existing users of bottom summaries; set it to `false` to restore the previous layout. + ### Changed +- **Breaking:** minimum OS versions raised and unified across KumikoUI.Maui and KumikoUI.Uno: iOS 17.0 (was 15.0 on MAUI, 14.2 on Uno), Mac Catalyst 17.0 (was 15.0, which current Xcode toolchains reject), Android API 24 (was 21), Windows 10.0.19041 (was 10.0.17763 on MAUI). Defined once in `Directory.Build.props` and re-baselined at each .NET major. +- **Breaking:** SkiaSharp 4.153.1 (was 3.119.2) for KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno, which changes the native SkiaSharp library in every consuming app. **Uno apps must set `4.153.1`** in their csproj: Uno.Sdk's implicit SkiaSharp packages default to 3.x, and the app must resolve the same major as KumikoUI. KumikoUI.Uno also references the SkiaSharp packages Uno's runtime pulls at 3.x (`SkiaSharp.Views`, `SkiaSharp.NativeAssets.Linux`, `SkiaSharp.Skottie`), so the whole graph resolves one major. +- **Breaking:** KumikoUI.Core, KumikoUI.SkiaSharp and every KumikoUI.Uno head now target .NET 10 (`net10.0`, `net10.0-*`); `net9.0` is dropped because .NET 9 support ends 2026-11-10. KumikoUI.Maui already targeted .NET 10. Apps must target .NET 10. - Supply-chain hardening: Dependabot (NuGet and GitHub Actions, grouped weekly), CodeQL analysis, OpenSSF Scorecard, read-only workflow tokens by default, and every GitHub Action pinned to a commit SHA at its current major (checkout v7, setup-dotnet v6, upload-artifact v7, download-artifact v8, action-gh-release v3). - Releases are gated: publishing requires approval in the `nuget-publish` environment and passing Core and Uno test suites; `main` and `v*` tags are protected by rulesets kept in `.github/settings/`. CI now runs on every pull request to `main`, including documentation-only changes, and no longer runs for `develop`. - Package versions come from git tags (MinVer); project files no longer contain `1.0.0`, so a local `dotnet pack` now produces a prerelease such as `0.2.0-alpha.0.8` instead of a misleading `1.0.0`. Copyright metadata uses a fixed year, and symbol packages are produced by default. -- **Breaking:** minimum OS versions raised and unified across KumikoUI.Maui and KumikoUI.Uno: iOS 17.0 (was 15.0 on MAUI, 14.2 on Uno), Mac Catalyst 17.0 (was 15.0, which current Xcode toolchains reject), Android API 24 (was 21), Windows 10.0.19041 (was 10.0.17763 on MAUI). Defined once in `Directory.Build.props` and re-baselined at each .NET major. - KumikoUI.Uno package description no longer claims a Mac Catalyst head (macOS is served by the desktop head). - KumikoUI.Maui now declares an explicit minimum of `Microsoft.Maui.Controls` 10.0.20 instead of whatever MAUI version the build machine had installed. - KumikoUI.Uno is built with Uno.Sdk 6.7.30 (was 6.5.31). -- **Breaking:** SkiaSharp 4.153.1 (was 3.119.2) for KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno, which changes the native SkiaSharp library in every consuming app. **Uno apps must set `4.153.1`** in their csproj: Uno.Sdk's implicit SkiaSharp packages default to 3.x, and the app must resolve the same major as KumikoUI. KumikoUI.Uno also references the SkiaSharp packages Uno's runtime pulls at 3.x (`SkiaSharp.Views`, `SkiaSharp.NativeAssets.Linux`, `SkiaSharp.Skottie`), so the whole graph resolves one major. -- **Breaking:** KumikoUI.Core, KumikoUI.SkiaSharp and every KumikoUI.Uno head now target .NET 10 (`net10.0`, `net10.0-*`); `net9.0` is dropped because .NET 9 support ends 2026-11-10. KumikoUI.Maui already targeted .NET 10. Apps must target .NET 10. - -### Added -- `DataGridStyle.PinBottomSummaryRows` (default `true`): `Position=Bottom` table summary rows are pinned to the bottom of the viewport as a fixed footer instead of scrolling after the last row. **Behaviour change** for existing users of bottom summaries; set it to `false` to restore the previous layout. ### Fixed - An unknown font family now falls back to the default family in the requested weight and slant instead of producing a null typeface. Styled typefaces are resolved through `SKFontManager` with an explicit family, which SkiaSharp 4 needs to keep bold and italic. - Taps on the pinned summary footer no longer select or edit the data row behind it; unpinned bottom summary rows are also reported as `HitRegion.TableSummaryRow`. - Keyboard navigation keeps the current row fully visible between the header/frozen rows and the pinned footer, and accounts for the grouping panel and top summary rows (previously the scroll offset was counted twice). - Row drag-handle grips no longer paint over the pinned summary footer. + +## [0.1.10] - 2026-05-05 + +### Added +- `SkiaFontRegistrar`: register custom typefaces (for example CJK or icon fonts) and use them by family name in `GridFont`. Fixes Japanese text and icon fonts rendering garbled on Android (#5, #8). + +### Fixed +- Sample: corrected the selection text colour property name in `IconFontCellRenderer`. + +## [0.1.9] - 2026-05-04 + +### Added +- Per-column `EditTriggers` on `DataGridColumn`, overriding the grid-level triggers (#6, #7). + +## [0.1.8] - 2026-05-03 + +### Added +- Action button columns: pill buttons in a cell with `ICommand` or callback support, activating on the first tap (#3). +- MIT licence and Contributor Covenant Code of Conduct. + +## [0.1.7] - 2026-03-06 + +### Changed +- README: NuGet installation steps in Getting Started. + +## [0.1.6] - 2026-03-06 + +### Changed +- NuGet package icon switched to PNG. + +## [0.1.4] - 2026-03-05 + +### Added +- NuGet package icon. + +## [0.1.3] - 2026-03-05 + +### Added +- First release on NuGet.org of KumikoUI.Core, KumikoUI.SkiaSharp and KumikoUI.Maui: a fully canvas-drawn DataGrid for .NET MAUI with virtual scrolling, text/numeric/boolean/date/combo/picker/image/template columns, sorting, Excel-style filtering, grouping with summaries, editing, selection, keyboard navigation, frozen columns and rows, row drag and drop, column resizing, theming and momentum scrolling. + +Versions 0.1.1, 0.1.2 and 0.1.5 were tagged but never published to NuGet.org. + +[Unreleased]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.10...HEAD +[0.1.10]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.9...v0.1.10 +[0.1.9]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.8...v0.1.9 +[0.1.8]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.7...v0.1.8 +[0.1.7]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.6...v0.1.7 +[0.1.6]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.4...v0.1.6 +[0.1.4]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.3...v0.1.4 +[0.1.3]: https://github.com/TheEightBot/KumikoUI/releases/tag/v0.1.3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e13beac..1e4c09a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,13 +74,18 @@ Package versions come from git tags through [MinVer](https://github.com/adamralp - Any other commit builds the next version as a prerelease, for example `0.2.0-alpha.0.8`: eight commits after the last tag. `MinVerMinimumMajorMinor` in `Directory.Build.props` sets the floor (currently 0.2). - Clones need tags and history (`git fetch --tags`, no shallow clone) or MinVer falls back to `0.2.0-alpha.0`. -To release, push a version tag on a commit that is on `main`: +To release: + +1. In [CHANGELOG.md](CHANGELOG.md), rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD`, add a fresh empty `## [Unreleased]` above it, and update the compare links at the bottom. Merge that through a pull request. Stable releases fail to publish without their section; prereleases fall back to `Unreleased`. +2. Push a version tag on that commit on `main`: ```bash git tag v0.2.0 git push origin v0.2.0 ``` +The section becomes the GitHub release notes, and every package links to the CHANGELOG. Versioning rules (SemVer, lockstep packages, deprecation, support window) are in [docs/VERSIONING.md](docs/VERSIONING.md). + The publish workflow refuses to run unless the ref is a version tag, the tagged commit is on `main`, and MinVer computes the same version as the tag. It then runs the Core and Uno test suites and waits for approval in the `nuget-publish` environment before pushing to NuGet.org. Symbol packages (`.snupkg`) are produced for every package by default. Only admins can create `v*` tags. ## Making a change diff --git a/Directory.Build.props b/Directory.Build.props index 0ec2b4d..968b3f1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,6 +23,7 @@ MIT https://github.com/TheEightBot/KumikoUI + Release notes for every version: https://github.com/TheEightBot/KumikoUI/blob/main/CHANGELOG.md https://github.com/TheEightBot/KumikoUI git diff --git a/docs/VERSIONING.md b/docs/VERSIONING.md new file mode 100644 index 0000000..40e8fe7 --- /dev/null +++ b/docs/VERSIONING.md @@ -0,0 +1,41 @@ +# Versioning and support policy + +## One version for all packages + +KumikoUI.Core, KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno are released together and always share the same version. Use the same version of every KumikoUI package in an app. Versions come from git tags (see [CONTRIBUTING.md](../CONTRIBUTING.md#versions-and-releases)). + +## Semantic Versioning + +KumikoUI follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html): `MAJOR.MINOR.PATCH[-prerelease]`. + +| Change | Before 1.0 (`0.y.z`) | From 1.0 | +|---|---|---| +| Breaking change to public API or documented behaviour | minor (`0.2.0` → `0.3.0`) | major | +| New feature, backward compatible | minor or patch | minor | +| Bug fix, backward compatible | patch | patch | +| Raised minimum OS, .NET or SkiaSharp major | minor | major | + +Before 1.0 the API is still settling: breaking changes can land in any minor release and are always listed under **Changed** with a **Breaking:** prefix in the [CHANGELOG](../CHANGELOG.md). + +Prerelease versions (`1.0.0-preview.1`, `0.2.0-alpha.0.8`) carry no compatibility promise. + +## What counts as public API + +- Every public type and member in the four packages, including XAML-settable properties and events. +- Documented behaviour: defaults, event order, rendering and input semantics described in the README or XML docs. +- The supported platforms and minimum versions in the README. + +Not covered: members marked internal or experimental, sample code, and pixel-exact rendering output (anti-aliasing can change with SkiaSharp updates). + +From 1.0, the public surface is tracked with API analyzers and package validation, so an unintended breaking change fails the build. + +## Deprecation + +From 1.0, a public API is removed only after it has been marked `[Obsolete]` with a message pointing to the replacement for at least one minor release; removal happens in the next major. Behaviour changes that cannot be deprecated are called out in the CHANGELOG and, where possible, kept behind an opt-in setting for one minor release. + +## Support window + +- **.NET:** each KumikoUI major targets the current .NET LTS release (currently .NET 10, supported until November 2028). When .NET moves to a new LTS, the next KumikoUI major moves with it; the previous major gets security fixes for six months. +- **Minimum OS versions** are re-baselined at each .NET major release; see the README's "Supported platforms". +- **Fixes:** bug and security fixes ship in the latest minor of the current major. Before 1.0, only the latest release is supported (see [SECURITY.md](../SECURITY.md)). +- **SkiaSharp, .NET MAUI and Uno Platform:** KumikoUI moves to new majors of its dependencies in its own minor (before 1.0) or major (from 1.0) releases, and states the required versions in the CHANGELOG. diff --git a/eng/changelog-section.sh b/eng/changelog-section.sh new file mode 100755 index 0000000..b1ddc92 --- /dev/null +++ b/eng/changelog-section.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Prints the body of one CHANGELOG.md section, without its heading. +# +# eng/changelog-section.sh 0.2.0 # section "## [0.2.0] - " +# eng/changelog-section.sh Unreleased # section "## [Unreleased]" +# +# Exits 1 if the section is missing or empty. +set -euo pipefail +version="${1:?usage: changelog-section.sh }" +file="${2:-$(cd "$(dirname "$0")/.." && pwd)/CHANGELOG.md}" + +body=$(awk -v v="$version" ' + /^## \[/ { + if (found) exit + if (index($0, "## [" v "]") == 1) { found = 1; next } + } + /^\[[^]]+\]: / { if (found) exit } # link reference definitions at the end + found { print } +' "$file" | sed -e '/./,$!d' | sed -e ':a' -e '/^\n*$/{$d;N;ba' -e '}') + +if [[ -z "${body//[[:space:]]/}" ]]; then + echo "CHANGELOG.md has no '## [$version]' section (or it is empty)." >&2 + exit 1 +fi +printf '%s\n' "$body"