Skip to content

ci(release): write the release page from a template, with an English summary - #196

Merged
fylorn merged 3 commits into
mainfrom
ci/release-notes-template
Sep 25, 2026
Merged

fylorn merged 3 commits into
mainfrom
ci/release-notes-template

Conversation

@fylorn

@fylorn fylorn commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

Release pages get a title and a fixed layout. A release is titled "ThinkWatch Core ", and its text is, in order: an English summary from release-notes/<version>.md when that file exists, a table of the files for each platform, the commands that install this version on a Linux server and switch an existing installation to it, how to verify a download against its .sha256, and GitHub's generated list of pull requests. Until now the page was only the generated list, under the bare tag.

Why

#191 fixed the list being written four times, but the page still did not say which file is for which platform, how to install twcore on a server, or how to check a download, and the tag alone made a poor title next to ThinkWatch Lite's releases.

How it works

  • scripts/release_notes.py <version> <generated list> writes the text. It refuses a malformed version, and a summary that is empty, contains Chinese characters or starts with a top-level heading (the workflow sets the title).
  • publish checks out the repository (before downloading the artifacts, since checkout cleans the workspace), asks releases/generate-notes for the list itself, runs the script, and hands the result to action-gh-release as body_path with name: ThinkWatch Core <version>. The action no longer generates anything.
  • The rule from Publish releases from one job; correct the server docs and crate metadata #191 stays: a release that already exists keeps its text (body_path is empty and the action leaves the body alone), and only release not found counts as "does not exist".
  • A rehearsal (workflow_dispatch) now also writes the text into the run summary, using the version in Cargo.toml, and still publishes nothing.
  • CONTRIBUTING's "Cutting a release" describes the text and where the summary goes.
  • release-notes/0.47.0.md summarizes 0.47.0 from Configuration reference, server deployment, and twcore upgrade #183-chore: v0.47.0 #190, and release-notes/0.48.0.md summarizes 0.48.0 from Publish releases from one job; correct the server docs and crate metadata #191-chore: v0.48.0 #198. v0.48.0 was published before this change, so its page still holds only the generated list; the 0.48.0 summary is there so the page can be rewritten from the template. Its upgrade notes cover CONTROL_API_VERSION 21 (ThinkWatch Lite 2026.9.16 includes 0.47.0, protocol 20, and does not connect to 0.48.0), the request store's schema 20 (the request history starts empty on the first start), and the changed /in-flight, RequestStarted and ChatgptUsage shapes.

FILES is unchanged, so twcore upgrade's test that reads release.yml is unaffected.

How it was verified

  • python3 scripts/release_notes_test.py: 17 tests, run on Python 3.14 and 3.9 (the Linux CI job has 3.10). They check that the table links exactly the seven files in FILES and that each has a .sha256 there, that the install.sh and twcore upgrade options in the commands exist, the checksum commands, the summary checks, and every file in release-notes/. Renaming one file in the table, or adding a Chinese line to a summary, fails them. The Linux CI job runs them before compiling.
  • actionlint with shellcheck on release.yml and ci.yml: clean.
  • The list from generate-notes for v0.47.0 is byte-identical to the list the v0.47.0 page carried before this change.
  • Rehearsal: run 36091692733 on this branch. All jobs passed (15 min). In Publish, the new step ran with the version from Cargo.toml (0.47.0) and wrote the text into the run summary; the release step was skipped, so nothing was published. The step's inputs are the committed release-notes/0.47.0.md and the generate-notes list for v0.47.0, so its output is the text now on the live v0.47.0 release, which was rendered locally from the same inputs.
  • Rebased onto main at v0.48.0. The body for v0.48.0 was rendered locally with scripts/release_notes.py 0.48.0 from the committed summary and the generate-notes list for v0.48.0, which is byte-identical to the list on the live v0.48.0 page. All seven files it links exist on the v0.48.0 release, each with its .sha256, and every link answers 200; the three checksum commands name files on the release. The rendered text has no CJK characters and renders through the GitHub Markdown API (one table, every bold label closed).

Notes for review

  • Code comments follow the language already used in release.yml; everything that reaches the release page is English.
  • The live v0.47.0 release page now has this layout and title; its text is the script's output for 0.47.0.

🤖 Generated with Claude Code

@fylorn
fylorn force-pushed the ci/release-notes-template branch from eb4934a to 07f659c Compare September 25, 2026 05:48
fylorn and others added 3 commits September 25, 2026 15:01
…summary

#191 made the publish job write the release once, with GitHub's
generated list of pull requests as its only text and the tag as its
title. A release is now titled "ThinkWatch Core <version>", and its text
has, in order:

- an English summary from release-notes/<version>.md, when that file
  exists;
- a table of the files for each platform;
- the commands that install this version on a Linux server and switch
  an existing installation to it (install.sh --version, twcore upgrade
  --version --restart);
- how to verify a download against its .sha256;
- GitHub's generated list of pull requests.

scripts/release_notes.py builds the text; the publish job fetches the
generated list itself (releases/generate-notes) and hands the finished
text to action-gh-release, which no longer generates anything. The
"only once" rule from #191 stays: a release that already exists keeps
its text. A rehearsal (workflow_dispatch) now writes the text into the
run summary, using the version in Cargo.toml.

scripts/release_notes_test.py checks that the table links exactly the
files in release.yml's FILES list, that the install and upgrade options
exist, and that every file in release-notes/ renders; the Linux CI job
runs it before compiling.

release-notes/0.47.0.md summarizes 0.47.0 from #183-#190; the live
v0.47.0 release page now carries it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.48.0 was published before the template landed, so its page holds
only GitHub's generated list. release-notes/0.48.0.md summarizes it
from #191-#198 so the page can be rewritten from the template:

- upgrade notes: CONTROL_API_VERSION 21, so ThinkWatch Lite 2026.9.16
  (core 0.47.0, protocol 20) does not connect to it and a server used
  with that app stays on 0.47.0; the request store's schema 20, which
  empties the request history on the first start (and again on the way
  back); the /in-flight shape, RequestStarted.session and the removed
  ChatgptUsage fields;
- session and route on the start event, requests a rule decided
  without an upstream, the replayable /in-flight snapshot and the new
  /live fields, and /summary/routes (#197);
- per-group unpriced and no-usage counts, and security log totals
  (#193);
- the signed-in account on a ChatGPT account upstream (#195);
- releases published from one job, the server guide and the crate
  metadata (#191), and the test port fix (#192).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eychain

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn force-pushed the ci/release-notes-template branch from ed149e3 to 54c6bd9 Compare September 25, 2026 07:01
@fylorn
fylorn merged commit 22fcc66 into main Sep 25, 2026
4 checks passed
@fylorn
fylorn deleted the ci/release-notes-template branch September 25, 2026 07:14
@fylorn fylorn mentioned this pull request Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant