From ea971d2aea4db1b4e30b8c472be12f1ea3883f92 Mon Sep 17 00:00:00 2001 From: thepra Date: Thu, 15 Oct 2026 09:22:16 +0200 Subject: [PATCH] Release notes written from the commits since the previous tag - The release page's "What's new" now comes from each commit's subject and body since the previous tag, without trailers or any line naming the assistant that helped write them. - `tools/release.sh notes` writes the notes alone; the release checkout fetches the tags. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB --- .gitea/workflows/release.yml | 2 ++ CLAUDE.md | 5 +++++ tools/release.cs | 37 +++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 02e023c..55d42e8 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -16,6 +16,8 @@ jobs: runs-on: nuvola steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Prepare run: .gitea/scripts/prepare.sh diff --git a/CLAUDE.md b/CLAUDE.md index 25b4123..2012dca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,6 +13,7 @@ dotnet run tools/setup.cs -- --group packaging # pinned nfpm into to dotnet build src/MeWeb.Android/MeWeb.Android.csproj \ -p:JavaSdkDirectory=$PWD/tools/jdk/linux-x64/jdk-21.0.12+8 -p:AndroidSdkDirectory=$HOME/Android/Sdk dotnet run --project tools/Screenshots -- dist/screenshots [en,it,...] +tools/release.sh notes # artifacts/release-notes.md alone, nothing built dotnet run tools/strings.cs -- check # every language against English dotnet run tools/strings.cs -- set Key values.json # one key, every language at once dotnet run tools/strings.cs -- merge keys.json # many keys: {"Key": {"en": "…", "it": "…"}} @@ -125,6 +126,10 @@ The Android release key: alias `meweb`, certificate SHA-256 themed icons), and the splash uses the same foreground. Both vectors hold `branding/meweb.svg`'s drawing scaled into the central 66 of 108 units around its smallest enclosing circle; a change to the drawing goes into all three files. The plain `mipmap-xxxhdpi/icon.png` is only for Android 7.x. +- **Release notes are the commits since the previous tag.** `tools/release.cs` writes "What's new" from each + commit's subject (without the `me-web? x.y:` prefix) and body, dropping trailers and any line that mentions Claude; + the release step needs `fetch-depth: 0` for the tags. So a commit body is written for the people who download the + release: plain words, one bullet per change they would notice. - **The macOS apphost is ad-hoc signed by the .NET 10 SDK even on Linux** (`LC_CODE_SIGNATURE` present); Apple Silicon refuses unsigned arm64 code, so never strip it. - **The Windows single-file publish drops native `.pdb` files beside the exe**; only `meweb.exe` ships. diff --git a/tools/release.cs b/tools/release.cs index 867444c..3e6ad69 100644 --- a/tools/release.cs +++ b/tools/release.cs @@ -22,9 +22,9 @@ if (version is null || !Regex.IsMatch(version, @"^\d+\.\d{1,2}\.\d{1,2}$")) } var words = args.Where((a, i) => !a.StartsWith("--", StringComparison.Ordinal) && (i == 0 || !args[i - 1].StartsWith("--", StringComparison.Ordinal))) .Select(a => a.ToLowerInvariant()).ToList(); -if (words.Count == 0 || words.Any(w => w != "all" && !targetNames.Contains(w))) +if (words.Count == 0 || words.Any(w => w != "all" && w != "notes" && !targetNames.Contains(w))) { - Console.Error.WriteLine("usage: tools/release.sh ... [--commit ]"); + Console.Error.WriteLine("usage: tools/release.sh ... [--commit ]"); return 2; } var targets = words.Contains("all") ? targetNames.ToList() : targetNames.Where(words.Contains).ToList(); @@ -37,6 +37,12 @@ var server = Path.Combine(root, "src", "MeWeb.Server", "MeWeb.Server.csproj"); var branding = Path.Combine(root, "branding"); Directory.CreateDirectory(output); Console.WriteLine($"me-web? {version} ({commit}): {string.Join(", ", targets)} -> {output}"); +if (targets.Count == 0) +{ + WriteNotes(); + Console.WriteLine(File.ReadAllText(Path.Combine(root, "artifacts", "release-notes.md"))); + return 0; +} var failed = false; if (targets.Any(t => t != "server")) @@ -72,19 +78,40 @@ return failed ? 1 : 0; void WriteNotes() { var source = Path.Combine(root, "artifacts", "knowledge", "SOURCE.txt"); - var lines = new List - { + var lines = Changes(); + lines.AddRange( + [ $"me-web? {version}, commit {commit}, built {builtAt}.", "", "Built with the provider map from iptoasn.com (PDDL 1.0):", "", - }; + ]); lines.AddRange(File.Exists(source) ? File.ReadAllLines(source).Where(l => l.Length > 0).Select(l => $" {l}") : [" (no provider map in this build)"]); lines.AddRange(["", "SHA256SUMS.txt lists every file. The APK's signing certificate SHA-256 is 5f52cff4f52f4e0b6da6cd044bfceaf78d1d42db24f2470602db7f19cbfdf846."]); Directory.CreateDirectory(Path.Combine(root, "artifacts")); File.WriteAllLines(Path.Combine(root, "artifacts", "release-notes.md"), lines); } +List Changes() +{ + var previous = Capture("git", "-C", root, "describe", "--tags", "--abbrev=0", "--match", "v*", "HEAD^").Trim(); + var log = Capture("git", "-C", root, "log", "--no-merges", "--reverse", "--format=%x1e%s%x1f%b", previous.Length > 0 ? $"{previous}..HEAD" : "HEAD"); + var lines = new List(); + foreach (var entry in log.Split('\x1e', StringSplitOptions.RemoveEmptyEntries)) + { + var parts = entry.Split('\x1f'); + var subject = Regex.Replace(parts[0].Trim(), @"^me-web\? [\d.]+:\s*", ""); + if (subject.Length == 0) continue; + var body = (parts.Length > 1 ? parts[1] : "").Split('\n').Select(l => l.TrimEnd()) + .Where(l => !Regex.IsMatch(l, @"^[A-Za-z-]+-(By|Session|Off-By):", RegexOptions.IgnoreCase)) + .Where(l => !l.Contains("claude", StringComparison.OrdinalIgnoreCase)) + .SkipWhile(l => l.Length == 0).Reverse().SkipWhile(l => l.Length == 0).Reverse().ToList(); + lines.AddRange([$"### {char.ToUpperInvariant(subject[0])}{subject[1..]}", ""]); + if (body.Count > 0) lines.AddRange([.. body, ""]); + } + return lines.Count == 0 ? [] : [$"## What's new in {version}", "", .. lines]; +} + string[] Stamp() => [$"-p:Version={version}", $"-p:BuildCommit={commit}", $"-p:BuildTimeUtc={builtAt}"]; string Linux()