Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
65355bc
feat(1.8.1): right-click coherence + Define discoverability
epheterson Jul 28, 2026
ee41a28
docs: date the 1.8.0 entry, drop a merge-duplicated 1.7.4 section
epheterson Jul 28, 2026
87301ad
feat(almanac): real bright-star field in the horizon scene
epheterson Jul 28, 2026
50b8a57
feat(1.8.1): anonymous-access policy (open/limited/private)
epheterson Jul 28, 2026
5454962
feat(1.8.1): Public access card + legible allowlist picker (UI)
epheterson Jul 28, 2026
0251886
feat(almanac): Worldwide holidays option + clickable region caption
epheterson Jul 28, 2026
044ebc1
fix(dym): widen did-you-mean coverage + long-word distance-2 (1.8.1)
epheterson Jul 28, 2026
cbf81cc
feat(1.8.1): private-mode login gate (client)
epheterson Jul 28, 2026
e868c10
feat(almanac): Location v2 — wider city set + full clock/map parity
epheterson Jul 28, 2026
4468d83
feat: snippet boilerplate-skip helper (previews.extract_snippet)
epheterson Jul 28, 2026
f0fdf4a
feat(1.8.1): anonymous-access policy core (users.py + http.py + tests)
epheterson Jul 28, 2026
d8a9798
test: make download-throttle tests hermetic
epheterson Jul 28, 2026
0f62413
feat(almanac): give the Almanac its own header identity
epheterson Jul 28, 2026
0ded958
test: cover start-now override for scheduled downloads
epheterson Jul 28, 2026
ce87691
feat(1.8.1): backup bundle + download start-now server endpoints
epheterson Jul 28, 2026
a7506e8
feat(1.8.1): download-scheduling card + backup hub UI
epheterson Jul 28, 2026
5306b60
feat(almanac): link-map expansion round 2 — 56 verified Q-IDs
epheterson Jul 28, 2026
4e543b2
i18n(1.8.1): download-schedule + backup keys (31 keys x10 locales)
epheterson Jul 28, 2026
330fe79
test: backup export/import server endpoints
epheterson Jul 28, 2026
3d1151d
feat(1.8.1): video-ZIM polish — mobile fit, resume, random-video card
epheterson Jul 28, 2026
903d33c
feat(1.8.1): zimgit PDF collections — first-class document list
epheterson Jul 28, 2026
a6dde5b
i18n: theme picker + darken-articles keys (x10 parity)
epheterson Jul 28, 2026
53d6583
feat(1.8.1): light theme tokens + app-theme control styles
epheterson Jul 28, 2026
15be46a
feat(1.8.1): app theme switch (Auto/Dark/Light) + auto-dark raw articles
epheterson Jul 28, 2026
18d9f45
chore(1.8.1): move desktop build entry-points to desktop/, playwright…
epheterson Jul 28, 2026
12e70ca
docs: replace static screenshots with a single walkthrough GIF
epheterson Jul 28, 2026
4efaf48
release: 1.8.1
epheterson Jul 28, 2026
5baec93
ci: snap publish waits for the desktop build to attach the asset
epheterson Jul 28, 2026
889512a
fix: Move to… stays in place in settings + submenu clamps to viewport
epheterson Jul 28, 2026
d172882
fix(a11y): light-theme WCAG contrast pass (toggles, badges, amber ink)
epheterson Jul 28, 2026
f3d4532
fix(almanac): segmented Regional/Worldwide pill, drop holiday-caption…
epheterson Jul 28, 2026
a3d8276
fix: Define chip clears iOS selection callout; drop reader-menu darke…
epheterson Jul 28, 2026
fcf5449
build: pull libtorrent by default where wheels exist; document BT knobs
epheterson Jul 28, 2026
e8fb821
fix(#38): scroll in place for same-page fragment links instead of a f…
epheterson Jul 28, 2026
8c358f1
fix(ui): tile-card TLC + deterministic badge layout
epheterson Jul 28, 2026
fed724e
test: private-mode login persistence + cookie-attribute coverage
epheterson Jul 28, 2026
2deebec
feat(bt): max concurrent downloads + max connections knobs (backend)
epheterson Jul 28, 2026
c5aff8a
fix(theme): kill Safari tab-switch flash + add Reader View Auto theme
epheterson Jul 28, 2026
c24d561
docs: correct BT wheel-coverage comments (musllinux covered, no sdist)
epheterson Jul 28, 2026
26e4090
fix(private-mode): iOS-zoom guard on inputs + hide inert Cancel in lo…
epheterson Jul 28, 2026
2532c7e
feat(1.8.1): gate sweep — backup v2 client residue + schedule-card po…
epheterson Jul 28, 2026
f91184b
fix(ui): light-mode card definition, disabled-field + blank-icon legi…
epheterson Jul 28, 2026
802a769
Revert "docs: replace static screenshots with a single walkthrough GIF"
epheterson Jul 29, 2026
526694a
docs: backlog onboarding tour note
epheterson Jul 29, 2026
9452dec
fix(private): fail closed on logout + stop SW caching identity endpoints
epheterson Jul 29, 2026
130fcf6
fix(#37): categories terminology + inline add, mobile drag, long-pres…
epheterson Jul 29, 2026
7db2a7d
fix(almanac): move holidays scope pill below calendar, drop caption
epheterson Jul 29, 2026
15a3552
feat(ui r3): tile full-lang chip, tighter top band, bulk downloads, a…
epheterson Jul 29, 2026
d4351bb
fix(health): flag broken-scrape ZIMs — empty media + empty articles
epheterson Jul 29, 2026
95800bb
feat(1.8.1): per-user server data storage + fuller server backup (sch…
epheterson Jul 29, 2026
d8309a0
feat(1.8.1): split backup hub into "My data" + "Server backup" cards
epheterson Jul 29, 2026
d3bcf58
feat(1.8.1): round-3 reconciliation — reader define/lookup polish, BT…
epheterson Jul 29, 2026
49f50fe
fix: admin sees full library in private/limited mode (session cookie)
epheterson Jul 29, 2026
a533ece
test: e2e admin private-mode library + reader; harden logout to gate
epheterson Jul 29, 2026
1425631
fix: revoke admin session cookies on manage-password rotation
epheterson Jul 29, 2026
baac4fb
Merge main into v1.8.1 ahead of the release PR
epheterson Jul 29, 2026
a06ff0d
docs: 1.8.1 changelog, release notes, README sync
epheterson Jul 29, 2026
2b132ad
docs: drop ambiguous city count from 1.8.1 almanac line
epheterson Jul 29, 2026
2a8344d
ci: auto-release preserves a curated draft's notes instead of overwri…
epheterson Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
name: Auto Release

# When a push to main changes the version, auto-tag and create a draft release.
# The draft body is pulled from CHANGELOG.md. Desktop builds attach assets.
# Only step left: review the draft and publish.
# ── Single-draft release flow (there must be exactly ONE draft per tag) ──────
# When a push to main changes the version in pyproject.toml:
# 1. this workflow tags vX.Y.Z and creates/updates the draft release, with
# notes pulled from CHANGELOG.md;
# 2. the tag push triggers desktop-release.yml, which builds every platform,
# signs the update enclosures, refreshes the appcasts, and attaches the
# built assets to the SAME draft (softprops matches the release by tag).
# 3. the maintainer reviews that one draft and publishes it;
# 4. publish-release.yml then ships PyPI + snap.
#
# The draft step below is IDEMPOTENT on purpose: `gh release create` would
# happily make a SECOND draft for a tag that already has one (GitHub does not
# enforce tag-uniqueness on drafts), which is exactly the duplicate "Zimi
# vX.Y.Z" draft that showed up next to a hand-curated one after PR #39. So if a
# release for the tag already exists (a maintainer-curated draft, or a re-run),
# we EDIT it instead of creating a duplicate.

on:
push:
Expand Down Expand Up @@ -78,7 +91,18 @@ jobs:
ENDNOTES
# Trim leading whitespace from heredoc
sed -i 's/^ //' /tmp/release-notes.md
gh release create "v${VERSION}" \
--draft \
--title "Zimi v${VERSION}" \
--notes-file /tmp/release-notes.md
# One draft per tag: update an existing release (curated draft or a
# re-run) instead of creating a duplicate. `gh release view` finds
# drafts by tag too.
if gh release view "v${VERSION}" >/dev/null 2>&1; then
# A curated draft already exists (a human wrote the release body).
# Preserve it — do NOT overwrite the notes with the changelog
# extract. The tag was created above; the draft binds to it on
# publish. This is the one-draft-per-tag path.
echo "Release v${VERSION} already exists — preserving its curated notes"
else
gh release create "v${VERSION}" \
--draft \
--title "Zimi v${VERSION}" \
--notes-file /tmp/release-notes.md
fi
24 changes: 15 additions & 9 deletions .github/workflows/desktop-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
gcc libcairo2-dev pkg-config python3-dev

- name: Install dependencies
run: pip install -r requirements-desktop.txt
run: pip install -r desktop/requirements-desktop.txt

- name: Install libtorrent (in-process BT engine)
shell: bash
Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
"

- name: Build with PyInstaller
run: pyinstaller --noconfirm zimi_desktop.spec
run: pyinstaller --noconfirm desktop/zimi_desktop.spec

# ── Post-build smoke tests ────────────────────────────────────────

Expand Down Expand Up @@ -459,8 +459,9 @@ jobs:

# Sign one enclosure and write its appcast.
# $1 label $2 file-to-sign $3 release-asset $4 outfile $5 min-sys line
# $6 extra enclosure attributes (e.g. sparkle:installerArguments)
generate_appcast() {
local LABEL="$1" FILE="$2" ASSET="$3" OUTFILE="$4" MINSYS="$5"
local LABEL="$1" FILE="$2" ASSET="$3" OUTFILE="$4" MINSYS="$5" ENC_EXTRA="$6"
if [ ! -f "$FILE" ]; then
echo "WARNING: No $LABEL enclosure found at $FILE"
return 1
Expand Down Expand Up @@ -493,7 +494,7 @@ jobs:
url="https://github.com/${REPO}/releases/download/${TAG}/${ASSET}"
length="${LENGTH}"
type="application/octet-stream"
sparkle:edSignature="${ED_SIG}"
sparkle:edSignature="${ED_SIG}"${ENC_EXTRA}
/>
</item>
</channel>
Expand All @@ -505,11 +506,16 @@ jobs:
}

MAC_MINSYS=$'\n <sparkle:minimumSystemVersion>12.0</sparkle:minimumSystemVersion>'
generate_appcast "Intel" "Zimi-Intel/Zimi-Intel.dmg" "Zimi-Intel.dmg" "appcast-intel.xml" "$MAC_MINSYS"
generate_appcast "Apple Silicon" "Zimi-AppleSilicon/Zimi-AppleSilicon.dmg" "Zimi-AppleSilicon.dmg" "appcast-arm64.xml" "$MAC_MINSYS"
# Windows enclosure is the Inno Setup installer; WinSparkle downloads
# and runs it to apply the update. No minimumSystemVersion line.
generate_appcast "Windows" "Zimi-windows-x64-Setup/Zimi-windows-x64-Setup.exe" "Zimi-windows-x64-Setup.exe" "appcast-windows.xml" ""
generate_appcast "Intel" "Zimi-Intel/Zimi-Intel.dmg" "Zimi-Intel.dmg" "appcast-intel.xml" "$MAC_MINSYS" ""
generate_appcast "Apple Silicon" "Zimi-AppleSilicon/Zimi-AppleSilicon.dmg" "Zimi-AppleSilicon.dmg" "appcast-arm64.xml" "$MAC_MINSYS" ""
# Windows enclosure is the Inno Setup installer; WinSparkle (0.9.4)
# downloads it, runs it with sparkle:installerArguments via
# ShellExecuteEx, then quits WITHOUT relaunching — so /SILENT gives a
# click-free progress-only update and the installer's [Run] entry does
# the relaunch (windows/zimi.iss). /SP- skips the "ready to install"
# prompt. Per-user install (no UAC), so silent is safe.
WIN_INSTALLER_ARGS=' sparkle:installerArguments="/SILENT /SP-"'
generate_appcast "Windows" "Zimi-windows-x64-Setup/Zimi-windows-x64-Setup.exe" "Zimi-windows-x64-Setup.exe" "appcast-windows.xml" "" "$WIN_INSTALLER_ARGS"

# Commit and push to main
git config user.name "github-actions[bot]"
Expand Down
17 changes: 13 additions & 4 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,21 @@ jobs:
- name: Download Snap from release
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ github.event.release.tag_name }}
run: |
VERSION="${{ github.event.release.tag_name }}"
gh release download "$VERSION" --repo epheterson/Zimi --pattern "*.snap" || true
SNAP_FILE=$(ls *.snap 2>/dev/null | head -1)
# The snap is attached by the Desktop Release workflow, which is
# usually still building when the release-published event fires.
# Poll for up to 60 minutes instead of racing it (the 1.8.0 snap
# silently missed the store because of this exact race).
for i in $(seq 1 30); do
gh release download "$VERSION" --repo epheterson/Zimi --pattern "*.snap" || true
SNAP_FILE=$(ls *.snap 2>/dev/null | head -1)
[ -n "$SNAP_FILE" ] && break
echo "Snap not attached yet (attempt $i/30) — waiting 2m"
sleep 120
done
if [ -z "$SNAP_FILE" ]; then
echo "No snap found in release $VERSION — skipping publish"
echo "No snap found in release $VERSION after 60m — skipping publish"
echo "SNAP_FOUND=false" >> $GITHUB_ENV
else
echo "Found: $SNAP_FILE"
Expand Down
Loading
Loading