| name | release |
| description | Release GenizahSearch โ version bump, What's New drafting, code review, build, deploy, GitHub release. Supports: web-only, desktop-only, or both. |
| user-invocable | true |
/release โ GenizahSearch Release Skill
You are orchestrating a release of GenizahSearch. This is a multi-step, partially interactive process. Follow each phase in order. Do NOT skip phases. Mark each phase clearly in your output.
Phase 0: Gather Release Intent
Ask the user:
- What version? (suggest next patch/minor/major based on current
version.py)
- What type? โ
web, desktop, or both
- One-line summary of the release theme (e.g., "Image adjustment controls")
Read version.py to show the current version. Read recent git log --oneline -20 and docs/OPEN_ISSUES.md to understand what's changed since last release.
Phase 1: Pre-Flight Code Review
Send an agent (subagent_type=Explore) to verify the code is ready:
Checks:
Report findings to the user. If there are blockers, stop and ask how to proceed. If there are warnings, list them and ask for confirmation to continue.
Phase 2: Interactive "What's New" Drafting (OPTIONAL)
Ask the user first: "Do you want to draft What's New / release texts now? You can do all, some, or skip entirely."
The user may choose any subset of the items below, or skip this phase entirely. Only draft what they ask for.
This is a multi-round interactive process. Do NOT rush it.
Step 2a: Gather material
- Read
git log --oneline since the last version tag
- Read recent entries in
CHANGELOG.md
- Identify the key user-facing changes (not internal refactors)
Step 2b: Draft requested release texts
Present drafts for whichever items the user wants. The full menu is:
-
CHANGELOG.md entry โ Full detailed changelog section with ### New Features, ### Improvements, ### Bug Fixes subsections as appropriate. Technical but readable.
-
README.md "What's New" section โ 1-2 paragraphs + bullet points for the version. User-facing, not too technical.
-
Web What's New banner (web/main.py near WHATS_NEW_VERSION) โ Single concise line, bilingual (English + Hebrew). This is what users see in the dismissible banner. Must be compelling but brief.
-
Desktop What's New bar (genizah_app.py WhatsNewBar.show_whats_new) โ Single line Hebrew summary shown in the notification bar.
-
Desktop What's New dialog (genizah_app.py WhatsNewDialog) โ 3-5 bullet points in Hebrew (<li> items), shown when user clicks "Learn More".
-
GitHub Release draft โ (skip for web-only releases โ no GitHub release will be created). Title + body for the GitHub release. Include:
- Release title:
vX.Y.Z: <theme>
- Summary paragraph
- Key changes (bullet points)
- Download links placeholder for desktop installer
-
Help page updates โ If new features need documentation:
web/pages/help.py โ both _create_english_content() and _create_hebrew_content()
Help.html โ desktop help file
Step 2c: Review loop
Present all requested drafts to the user at once. Ask:
"Please review these drafts. Tell me what to change โ wording, emphasis, additions, removals. We can do as many rounds as you need."
Iterate until the user approves. Pay attention to:
- Hebrew quality (the user is a native speaker)
- Consistency across chosen text locations
- Proper bilingual coverage (EN + HE)
Phase 3: Version Bump + Apply Texts
Once texts are approved (or Phase 2 was skipped):
- Run
python scripts/bump_version.py X.Y.Z โ updates version.py, version_info.txt, CompileScriptGenizah.iss, README.md
- Apply all approved text changes (only those drafted in Phase 2):
- Edit
CHANGELOG.md โ add the approved section at top
- Edit
README.md โ update "What's New" section
- Edit
web/main.py โ update the What's New banner text
- Edit
genizah_app.py โ update WhatsNewBar message + WhatsNewDialog content
- Edit
CLAUDE.md "Recently Changed" section โ add entry
- Edit help files if applicable
- Run
python scripts/check_docs.py to verify docs are still healthy
- Update
docs/OPEN_ISSUES.md โ mark any fixed issues, update timestamp
Phase 4: "Did You Forget?" Checklist
Present this checklist BEFORE building or deploying. Adapt it based on what was done in Phase 2 (mark N/A for skipped items):
RELEASE CHECKLIST โ vX.Y.Z
==============================
[ ] Version bumped in all files (version.py, .iss, version_info.txt, README)
[ ] tests/test_release_artifacts.py _TARGET_VERSION manually bumped (bump_version.py misses it)
[ ] CHANGELOG.md has new section with correct date
[ ] README.md "What's New" updated (or N/A)
[ ] CLAUDE.md "Recently Changed" updated
[ ] Web What's New banner text updated (or N/A)
[ ] Desktop What's New bar + dialog updated (or N/A)
[ ] Help pages updated (or N/A)
[ ] OPEN_ISSUES.md up to date
[ ] All tests passing
[ ] ruff explicit pass (python -m ruff check .)
[ ] requirements.txt โ requirements-lock.txt diff is empty (CI uses the lock file; missing deps break CI)
[ ] No uncommitted changes (besides release changes)
[ ] Translations present for new UI strings
FOR DESKTOP:
[ ] Sidecar databases checkpointed (build_app.bat does this)
FOR WEB:
[ ] No breaking changes to web-only features
Ask: "Anything else you want to verify before we build and deploy?"
Phase 5: Release Summary + Confirmation
Present a human-readable summary of what this release contains and what will happen. This is the "read it aloud to a colleague" version โ plain English, no file paths or technical jargon.
Part A โ What's in this release:
Summarize the user-facing changes in plain language. Group by:
- New features โ what can users do now that they couldn't before?
- Improvements โ what got better/faster/easier?
- Bug fixes โ what was broken and is now fixed?
- Internal/infrastructure โ anything non-user-facing worth noting (briefly)
Keep each item to one sentence. Write as if explaining to a non-technical stakeholder.
Example:
New features: Users can now adjust brightness and contrast on manuscript images directly in the viewer.
Bug fixes: Fixed an issue where Oxford metadata would incorrectly appear on Russian National Library manuscripts.
Part B โ What will happen next:
ACTIONS โ vX.Y.Z: <theme>
===================================
Commit & tag: vX.Y.Z on master-main
Desktop build: PyInstaller + Inno Setup installer (or "skipped โ web only")
Web deploy: deploy.sh on EC2 (or "skipped โ desktop only")
GitHub release: with installer upload (or "skipped โ web only")
Ask: "Does this look right? Proceed with build and deploy?"
Phase 6: Build (Desktop only โ skip for web-only releases)
Running build_app.bat reliably (learned the hard way โ v8.0.0 burned ~5 failed
attempts). A bare cmd /c build_app.bat from the PowerShell/Bash tool fails with
'build_app.bat' is not recognized for THREE compounding reasons, all defeated by the
invocation below:
- Background tasks don't inherit the project CWD โ they start elsewhere, not the repo root.
- PowerShell
Set-Location only moves the provider location, NOT the process working
directory a spawned cmd inherits โ you MUST also set [Environment]::CurrentDirectory.
(Start-Process -WorkingDirectory is ignored when combined with output redirection โ
don't rely on it either.)
- This machine has
NoDefaultCurrentDirectoryInExePath set, so cmd refuses to search
the current dir for the batch file โ you MUST pass the explicit full path to the .bat.
(The .bat still uses relative paths internally โ genizah_app.py, icon.ico, scripts\โฆ โ
so the process CWD must ALSO be the repo root; that's why both pieces are needed.)
Proven invocation (PowerShell tool; OK to run in background):
Set-Location -LiteralPath 'C:\Genizahsearch'; [Environment]::CurrentDirectory = 'C:\Genizahsearch'; cmd /c "C:\Genizahsearch\build_app.bat"; Write-Output "BUILD_EXIT=$LASTEXITCODE"
- Run
build_app.bat (via the invocation above) โ PyInstaller build (several minutes)
- Verify
dist/GenizahSearchPro/GenizahSearchPro.exe exists after build
build_app.bat REGENERATES (clobbers) GenizahSearchPro.spec every run (command-line
PyInstaller writes a fresh minimal spec, stripping the maintained collect_all('pymupdf')/
collect_all('zstandard')/collect_all('lxml') + fitz/openpyxl/defusedxml
hidden-imports). The build still works (PyInstaller contrib hooks collect those deps), but
after the build run git restore GenizahSearchPro.spec so the maintained spec is never
committed clobbered.
- Run Inno Setup CLI to create installer (same CWD caveat โ full paths):
Set-Location -LiteralPath 'C:\Genizahsearch'; [Environment]::CurrentDirectory = 'C:\Genizahsearch'; & 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' 'C:\Genizahsearch\CompileScriptGenizah.iss'; Write-Output "ISCC_EXIT=$LASTEXITCODE"
- Verify the output
.exe installer was created (dist/GenizahSearchPro_VX.Y.Z_Setup.exe)
- (Inno compresses the ~2.3 GB payload with LZMA โ allow ~5 min.)
- Report build output sizes to user
Desktop Installer Test Gate
Do NOT proceed to deploy until the user confirms they tested the installer.
Ask: "Please install and launch the built installer to verify it works. Confirm when ready to continue."
Wait for the user's confirmation before moving to Phase 7.
Phase 7: Commit, Tag & Deploy
After user confirms:
-
Stage and commit all release changes:
git add -A
git commit -m "release: vX.Y.Z โ <theme>"
-
Tag the release:
git tag -a vX.Y.Z -m "vX.Y.Z: <theme>"
-
Push (ask for confirmation first):
git push origin master-main --tags
3.5. REQUIRED โ Watch CI on the release commit. Never assume CI will pass just because the local pytest run passed. CI installs from requirements-lock.txt (not requirements.txt), runs on Ubuntu-latest with Python 3.11, and exercises a different subset of the suite. The local test run can be green while CI fails to even collect tests (the v7.14.0 release hit exactly this: 8 collection errors on ModuleNotFoundError: No module named 'fitz' because pymupdf was missing from the lock file).
gh run list --branch master-main --limit 3
gh run watch <run-id>
Alternatively, use the Monitor tool with a polling gh run view loop until the run reaches completed status.
If CI passes: continue to step 4 (deploy web).
If CI fails: STOP. Do NOT deploy to production with a red CI run on the release commit. Read the failure logs (gh run view <id> --log-failed), diagnose root cause, push a hotfix commit, and re-watch CI. Only proceed to deploy once CI is green. (For the v7.14.0 incident the user accepted that web+desktop were already deployed and live, but the right default is to gate deploy on CI โ not parallel.)
-
Deploy web (if web or both):
- Run:
ssh ubuntu@ec2-44-247-206-248.us-west-2.compute.amazonaws.com "cd /home/ubuntu/GenizahSearch && ./deploy.sh"
- Verify service restarted successfully
-
Web smoke test (if web or both):
- Use WebFetch to GET
https://genizahsearch.com โ verify HTTP 200
- Check that the response body contains the new version string (X.Y.Z)
- If the smoke test fails, alert the user immediately and suggest rollback (see Phase 9)
-
Create GitHub Release โ DESKTOP OR BOTH ONLY. NEVER for web-only releases.
Why this matters: the installed desktop app polls https://api.github.com/repos/gershuni/GenizahSearch/releases/latest (UpdateCheckerThread in gui_threads.py:445) and prompts every desktop user to update whenever a new tag becomes latest. A web-only GitHub release has no installer attached, so the prompt sends users to a release page they cannot install from. Past incident: v7.9.3 (web-only) created a release, every desktop user was prompted to "update" to a no-installer page.
-
Post-deploy verification:
- For web: confirm smoke test passed, suggest user also checks manually
- For desktop: remind to verify the installer download works from GitHub releases
Phase 8: Wrap Up
- Summarize what was released
- Final CI confirmation: run
gh run list --branch master-main --limit 3 and confirm the latest run (release commit + any hotfixes) is completed success. If still in-progress, set a Monitor and don't declare the release done until it lands green.
- List any deferred items or known issues for next release
- Remind about any follow-up tasks (e.g., "announce to users", "monitor error tracking")
Phase 9: Rollback (only if something goes wrong)
This phase is NOT part of the normal flow. Only use if the deploy fails or the user reports a critical issue.
Web rollback:
ssh ubuntu@ec2-44-247-206-248.us-west-2.compute.amazonaws.com "cd /home/ubuntu/GenizahSearch && git checkout HEAD~1 && sudo systemctl restart genizah-web"
Desktop rollback:
- The previous installer is still on GitHub releases โ users can download it
- No action needed server-side
Git rollback (if needed):
git revert HEAD --no-edit
git push origin master-main
Always explain what happened and why before executing any rollback.