Skip to main content

release-version

Steps to cut a VNote version release (e.g. v4.3.0) — bump the version with scripts/update_version.py, refresh and fill zh_CN/ja translations via lupdate, write the changes.md changelog, and trigger the CI [Release] build. Use when asked to "release", "cut a release", "bump the version", or "prepare vX.Y.Z".

Informations de source

Dépôt
vnotex/vnote
Dernière activité de la source
24 septembre 2026 à 13:40
Langue détectée de SKILL.md
anglais
Étoiles
12 987
Forks
1 296

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
release-version
description
Steps to cut a VNote version release (e.g. v4.3.0) — bump the version with scripts/update_version.py, refresh and fill zh_CN/ja translations via lupdate, write the changes.md changelog, and trigger the CI [Release] build. Use when asked to "release", "cut a release", "bump the version", or "prepare vX.Y.Z".
# VNote Version Release End-to-end checklist for releasing a new VNote version. Replace `X.Y.Z` with the target version (e.g. `4.3.0`) throughout. ## 0. Preconditions - You are on `master` (releases are published from `master`), working tree clean except for the release changes. - Decide `X.Y.Z`. Confirm the previous tag with `git tag | Sort-Object -Descending`. - Submodules are already pinned to their intended commits (see root `AGENTS.md` § Submodule Push Discipline — push submodules BEFORE the parent). ## 1. Bump the version (use the script — do NOT hand-edit) ```pwsh python scripts/update_version.py X.Y.Z ``` `scripts/update_version.py` is the single source of truth. It updates: - `CMakeLists.txt` — `project(... VERSION X.Y.Z ...)` - `.github/workflows/ci-win.yml`, `ci-linux.yml`, `ci-macos.yml`, `ci-linux-tsan.yml` — `VNOTE_VER: X.Y.Z` - `src/data/core/Info.plist` — short (`X.Y`) and full (`X.Y.Z`, `X.Y.Z.1`) strings - `src/core/configmgr2.cpp` — `ConfigMgr2::c_version{X, Y, Z}` - `src/data/core/fun.vnote.app.VNote.metainfo.xml` — prepends a dated `<release>` entry Note: `ci-linux-tsan.yml` IS in the script's file list (`scripts/update_version.py:21`) and the `[Release] VNote 4.3.0` commit `a282ef07` bumped it too, so keep the script's change. Its `VNOTE_VER` is only a build sanity value and does not publish anything — it just tracks the release version. Verify: `git diff --stat` should show exactly the files listed above. ## 2. Update translations (extract, then fill, both locales) The two maintained catalogs are `src/data/core/translations/vnote_zh_CN.ts` (Simplified Chinese) and `vnote_ja.ts` (Japanese). ### 2a. Extract new/changed strings with lupdate `lupdate` ships with Qt, and the installed Qt version changes over time — do NOT hardcode a path (`C:\Qt\6.9.3\...` was already gone by 4.3.1). Resolve it first: ```pwsh $lupdate = (Get-Command lupdate -ErrorAction SilentlyContinue).Source if (-not $lupdate) { $lupdate = (Get-ChildItem C:\Qt -Recurse -Filter lupdate.exe -ErrorAction SilentlyContinue | Where-Object FullName -like '*msvc*' | Sort-Object FullName -Descending | Select-Object -First 1).FullName } $lupdate # e.g. C:\Qt\6.10.3\msvc2022_64\bin\lupdate.exe ``` ```pwsh & $lupdate -no-obsolete -locations relative src ` -ts src/data/core/translations/vnote_zh_CN.ts src/data/core/translations/vnote_ja.ts ``` - `-no-obsolete` drops entries no longer in the source (keeps the catalog lean). - Harmless `pdf.js` JS parse errors are expected — lupdate still finishes. - The summary reports "N new" strings; those become `type="unfinished"`. ### 2b. Fill in the unfinished translations Every `type="unfinished"` entry must be translated for BOTH locales. Count them: ```pwsh (Select-String -Path "src/data/core/translations/vnote_zh_CN.ts" -Pattern 'type="unfinished"').Count (Select-String -Path "src/data/core/translations/vnote_ja.ts" -Pattern 'type="unfinished"').Count ``` Extract the source strings needing translation, then for each `<message>` whose `<translation type="unfinished">` is empty, provide the localized text and drop the `type="unfinished"` attribute (`<translation>...</translation>`). Practical approach: script it. Build a `source -> translation` map per locale and rewrite each unfinished `<message>` block, escaping `&`/`<`/`>` in the output and preserving `%1`/`%2` placeholders, `&`-accelerators (e.g. `&View` -> `查看(&V)` / `表示(&V)`), and literal newlines. Re-run the count above; both must reach `0`. Two traps when scripting the rewrite: - **Anchor the `<source>` capture.** A pattern like `<source>(.*?)</source>` with `(?s)` lets the group swallow whole `</message>` blocks to reach a *later* unfinished `<translation>`, silently deleting every message in between (a whole `<context>` disappeared this way during 4.3.1). Forbid the closing tag inside the group and stop the gap before the next message: `<source>((?:(?!</source>).)*)</source>((?:(?!</message>|<source>).)*?)<translation type="unfinished">` - **Numerus entries** are `<translation type="unfinished"><numerusform></numerusform></translation>`. Fill the `<numerusform>` rather than replacing the element body, so the plural structure and indentation survive. Then VERIFY against the pre-edit file — an over-matching regex leaves the counts looking fine while having eaten unrelated entries: ```pwsh foreach ($l in 'zh_CN','ja') { git show "HEAD:src/data/core/translations/vnote_$l.ts" > "$env:TEMP\old_$l.ts" $o = [xml](Get-Content -Raw "$env:TEMP\old_$l.ts") $n = [xml](Get-Content -Raw "src/data/core/translations/vnote_$l.ts") # NOTE: PowerShell's XML adapter returns a bare string for <translation> once # the type attribute is gone, so .InnerText is $null — normalize first. function Tr($m) { $t = $m.translation; if ($null -eq $t) { '' } elseif ($t -is [string]) { $t } else { $t.InnerText } } $old = @{}; foreach ($c in $o.TS.context) { foreach ($m in $c.message) { $old["$($c.name)|$($m.source)"] = (Tr $m) } } $changed = 0; $bad = 0 foreach ($c in $n.TS.context) { foreach ($m in $c.message) { $k = "$($c.name)|$($m.source)"; $tr = (Tr $m) if ($old.ContainsKey($k)) { if ($old[$k] -ne $tr) { $changed++; "CHANGED $k" }; continue } $ps = @([regex]::Matches($m.source, '%\d|%n') | ForEach-Object { $_.Value } | Sort-Object -Unique) $pt = @([regex]::Matches($tr, '%\d|%n') | ForEach-Object { $_.Value } | Sort-Object -Unique) if (($ps -join ',') -ne ($pt -join ',')) { $bad++; "PLACEHOLDER $k" } } } "$l changed_existing=$changed placeholder_mismatch=$bad" } ``` `changed_existing` MUST be 0 (only lupdate's own obsolete removals may drop keys — cross-check them against `git log` / the source tree) and `placeholder_mismatch` MUST be 0. Finally, compile both catalogs; each must report `0 unfinished`: ```pwsh foreach ($l in 'zh_CN','ja') { & ($lupdate -replace 'lupdate\.exe$','lrelease.exe') "src/data/core/translations/vnote_$l.ts" -qm "$env:TEMP\$l.qm" } Remove-Item "$env:TEMP\zh_CN.qm","$env:TEMP\ja.qm" ``` The `.qm` binaries are generated at build time by the `lrelease` CMake target (see `src/CMakeLists.txt`), so you do NOT commit `.qm` files. ## 3. Write the changelog Prepend a new `## vX.Y.Z` section at the TOP of `changes.md` (right under the `# Changes` header, above the previous version). - Summarize `git log <prev-tag>..HEAD --oneline` grouped by theme (Editor, Export, Tasks, Fixes, Security, Translations, …), matching the style of existing entries. - Lead with a one-line summary sentence "… on top of VNote <prev>:". - If an `## Unreleased` section exists, FOLD it into the new `## vX.Y.Z` section (it is not a separate release) rather than leaving both. - Always end with a **Translations** bullet noting zh_CN + ja were updated. ## 4. Review Use the read-only `checkpoint-reviewer` agent for both required checkpoints: once after the release plan is ready, before edits, and again after implementation and verification, before committing. Resolve blockers and investigate concerns; the primary owns validation, so tell the reviewer to skip builds and tests. ## 5. Commit and trigger the release CI publishes a (draft) GitHub release from `master` ONLY when the head commit message starts with `[Release]` (see the `Release` job in each `ci-*.yml`; condition: `github.ref == 'refs/heads/master' && startsWith(head_commit.message, '[Release]')`). It creates tag `vX.Y.Z` and uploads the platform artifacts. Release commits skip test compilation, registration checks, test runs and failure reruns on Linux, macOS and Windows; the test-only TSan job is skipped entirely. Packaging, signing and package-integrity checks still run. Normal pushes, pull requests and manual runs retain testing (Windows Qt 5 remains packaging-only). A green release run is not test-suite evidence; use a non-release run for that. - Commit message MUST start with `[Release]`, e.g. `[Release] VNote X.Y.Z`. - Follow repo `AGENTS.md` rule 13 for author/commit date (night-time), and only commit when the user explicitly asks. - If submodule pointers moved, push submodules first, then the parent (rule + root `AGENTS.md` § Submodule Push Discipline). ## 6. Once CI is green, assemble the draft release The `[Release]` commit makes CI create a **draft** GitHub release for tag `vX.Y.Z`. Wait until ALL platform jobs are green, then make sure the draft carries the five platform packages before publishing. The `ncipollo/release-action` step in each `ci-*.yml` uploads its own platform's asset directly, but confirm all five are present (and if any job's upload was skipped/failed, download that job's build artifact and attach it manually). The five required platform packages (additional installers/update assets may also be present): | Platform | Artifact file | Produced by | |----------|---------------|-------------| | Linux | `VNote-X.Y.Z-linux-x64.AppImage` | `ci-linux.yml` | | macOS 13+ (Qt 6.10.3) | `VNote-X.Y.Z-mac-universal.dmg` | `ci-macos.yml` (suffix `""`) | | macOS 12.1+ (Qt 6.9.3) | `VNote-X.Y.Z-mac-universal-macos12.dmg` | `ci-macos.yml` (suffix `-macos12`) | | Win64 (Qt 6) | `VNote-X.Y.Z-win64.zip` | `ci-win.yml` (suffix `""`) | | Windows 7 (Qt 5.15) | `VNote-X.Y.Z-win64-windows7.zip` | `ci-win.yml` (suffix `-windows7`) | Both macOS packages are universal (`x86_64` + `arm64`) and built on `macos-latest`. The `-macos12` suffix describes the deployment target, not the runner OS; its minimum is 12.1, matching VNote's existing deployment floor. Keep each variant's CMake deployment target and bundle `LSMinimumSystemVersion` aligned. Verify the compatibility package launches and renders Markdown preview on Intel macOS 12.7.6 before claiming Monterey compatibility; a newer CI runner cannot establish that. Continuous builds retain both `VNote-continuous-mac-universal.dmg` and `VNote-continuous-mac-universal-macos12.dmg` with independent pruning. Watch the runs and confirm the draft, using `gh`: ```pwsh # Watch the release-triggering runs on master until they finish. gh run list --branch master --limit 8 gh run watch <run-id> # Inspect the draft release and its currently-attached assets. gh release view vX.Y.Z ``` If an asset is missing, download it from the corresponding workflow run and upload it to the draft: ```pwsh # Download the build artifact(s) from a finished run into ./_artifacts. gh run download <run-id> -D _artifacts # Attach a missing asset to the draft release (repeat per file). gh release upload vX.Y.Z "_artifacts\<path>\VNote-X.Y.Z-...zip" --clobber ``` ### Set the release description from `changes.md` The draft's body is driven from `## vX.Y.Z` section of `changes.md` (the same changelog written in step 3) focusing on user experience changes. CI creates the release with an empty body, so set it. ```pwsh # Extract the ## vX.Y.Z section into a temp notes file... $ver = "X.Y.Z" $md = Get-Content changes.md -Raw $sec = [regex]::Match($md, "(?ms)^## v$([regex]::Escape($ver))\b.*?(?=^## |\z)").Value.TrimEnd() Set-Content -Path notes.md -Value $sec -NoNewline -Encoding utf8 # ...and apply it as the draft's description after rewriting it to focus on user experience changes. gh release edit vX.Y.Z --notes-file notes.md ``` Drop the leading `## vX.Y.Z` line if you prefer the version to appear only as the release title; keep the bullet body either way. Verify with `gh release view vX.Y.Z`. `ncipollo/release-action` REPLACES the body and the name on every update unless told not to, and all five platform jobs target the same draft with `allowUpdates: true`. Before 4.4.2 that silently blanked the notes: whichever job finished last wiped them, `gh release view` then showed an empty body, and the Gitee mirror — which copies the GitHub body — fell back to the bare tag name. The three `ci-*.yml` Release steps now pass `omitBodyDuringUpdate: true` and `omitNameDuringUpdate: true`, so notes set at any point after the release exists survive. If you ever see the body empty again, check those inputs are still there before re-typing the notes. ### Publish Only when the draft `vX.Y.Z` release shows all **5** platform packages (linux / macos / macos12 / win64 / windows7) AND its body matches the `changes.md` section do you publish it: ```pwsh gh release edit vX.Y.Z --draft=false ```
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub