rebrand: MangaBM → BookmarkManager, add novel library support (#15)
Two intertwined changes — the rebrand and the novel library were developed on
the same branch because the novel UI plumbing is part of the new "Bookmark
Manager" wordmark in the web shell.
## What it does
- **Rebrand**: MangaBM → BookmarkManager across the Go module, compose stack,
env vars, Traefik hostnames, container/image names, userscript storage
prefixes (`mangabm:cache` → `bmgr:manga:cache`, `mangabm:queue` → `bmgr:manga:queue`),
and docs.
- **Novel library**: same backend, two libraries. New `kind` column splits
bookmarks into `manga` / `novel`; PUT validates it. Two userscripts:
- `manga-bookmark.user.js` — unchanged behaviour, just stamps its own `kind`.
- `novel-bookmark.user.js` — separate Violentmonkey install with adapters
for **novelfull.com** (polled via headless browser — Cloudflare JS
challenge) and **lightnovelworld.net** (polled via plain TLS).
- **Web UI**: library switch on the app shell. Login art, libswitch, and
novel-site colours from the Cinder design snapshot.
## Plumbing
- `addedColumns` ALTER for `kind` runs on first start after upgrade; every
pre-existing row is backfilled to `'manga'`. No manual SQL, no down-time.
- `ALLOWED_ORIGINS` gains the two novel sites.
- New `NOVEL_USERSCRIPT_PATH` env (default `/userscript/novel-bookmark.user.js`),
bindmounted alongside the manga script.
- Traefik router names `mangabm*` → `bmapi*` / `bmweb*`.
## Test status
- `go test ./...` — green
- `node --test userscript/test/logic.test.js` — 34 pass
- `node --test userscript/test/novel-logic.test.js` — 11 pass
- `node --check` on both userscripts — clean
## Notes for the redeploy
.env keys were renamed (`MANGA_API_HOST` → `BOOKMARK_API_HOST`,
`MANGA_WEB_HOST` → `BOOKMARK_WEB_HOST`). Update DNS / Traefik labels on the
prod override before pulling, otherwise the public hostnames go dark.
See the redeploy instructions I'll post next to this PR.
Reviewed-on: #15
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
This commit was merged in pull request #15.
This commit is contained in:
+20
-20
@@ -9,16 +9,16 @@ Whole thing is ~5 minutes, most of it waiting on `docker build`. Order matters:
|
||||
**back up before you pull.** A backup taken after a bad migration is a backup of
|
||||
the damage.
|
||||
|
||||
Paths below assume the checkout is at `/opt/mangabm`; substitute your own. The
|
||||
one absolute rule about paths: **backups live in `../mangabm-backups/`**, a
|
||||
sibling of the project directory (`/opt/mangabm-backups`), never inside it. It
|
||||
Paths below assume the checkout is at `/opt/bookmarkmanager`; substitute your own. The
|
||||
one absolute rule about paths: **backups live in `../bookmarkmanager-backups/`**, a
|
||||
sibling of the project directory (`/opt/bookmarkmanager-backups`), never inside it. It
|
||||
sits outside the repo so `git pull`, `git clean -fd` and a bad `rm -rf` inside
|
||||
the checkout cannot take the backups with them.
|
||||
|
||||
```
|
||||
/opt/
|
||||
├── mangabm/ <- the checkout (this repo)
|
||||
└── mangabm-backups/ <- bookmarks-YYYYmmdd-HHMMSS.db
|
||||
├── bookmarkmanager/ <- the checkout (this repo)
|
||||
└── bookmarkmanager-backups/ <- bookmarks-YYYYmmdd-HHMMSS.db
|
||||
```
|
||||
|
||||
---
|
||||
@@ -26,12 +26,12 @@ the checkout cannot take the backups with them.
|
||||
## 0. Preflight
|
||||
|
||||
```bash
|
||||
cd /opt/mangabm
|
||||
cd /opt/bookmarkmanager
|
||||
|
||||
# Both -f flags, every time. The prod override is not standalone.
|
||||
COMPOSE="docker compose -f docker-compose.yml -f docker-compose.prod.yml"
|
||||
|
||||
$COMPOSE ps # manga-api should be Up
|
||||
$COMPOSE ps # bookmark-api should be Up
|
||||
git status --short # expect empty
|
||||
git log --oneline -1 # note this hash — it is your rollback target
|
||||
df -h /var/lib/docker | tail -1 # a build needs room
|
||||
@@ -44,9 +44,9 @@ dirty tree fails halfway and leaves you in a worse spot than either.
|
||||
Create the backup directory once, and make sure it is a sibling, not a child:
|
||||
|
||||
```bash
|
||||
mkdir -p ../mangabm-backups
|
||||
BACKUP_DIR="$(cd .. && pwd)/mangabm-backups" # absolute — Docker needs it
|
||||
echo "$BACKUP_DIR" # -> /opt/mangabm-backups
|
||||
mkdir -p ../bookmarkmanager-backups
|
||||
BACKUP_DIR="$(cd .. && pwd)/bookmarkmanager-backups" # absolute — Docker needs it
|
||||
echo "$BACKUP_DIR" # -> /opt/bookmarkmanager-backups
|
||||
```
|
||||
|
||||
---
|
||||
@@ -59,7 +59,7 @@ prefixes it with the project directory:
|
||||
|
||||
```bash
|
||||
docker volume ls --filter name=bookmarks-data
|
||||
# -> local mangabm_bookmarks-data
|
||||
# -> local bookmarkmanager_bookmarks-data
|
||||
VOL=$(docker volume ls --filter name=bookmarks-data -q | head -1)
|
||||
```
|
||||
|
||||
@@ -172,11 +172,11 @@ bindmounted read-only and read fresh per request.
|
||||
|
||||
```bash
|
||||
$COMPOSE ps # Up, and recently (re)created
|
||||
docker logs manga-api --tail 20 # -> "listening on :8080 ..."
|
||||
docker logs bookmark-api --tail 20 # -> "listening on :8080 ..."
|
||||
```
|
||||
|
||||
Nothing in the log about the database or the poller failing. The image is tagged
|
||||
`mangabm-backend:latest`, so the previous image is still on disk untagged —
|
||||
`bookmarkmanager-backend:latest`, so the previous image is still on disk untagged —
|
||||
that is what makes the rollback in §6 quick.
|
||||
|
||||
---
|
||||
@@ -186,8 +186,8 @@ that is what makes the rollback in §6 quick.
|
||||
Same four API checks as `DEPLOY.md` §3, plus the web UI. Set the host names once:
|
||||
|
||||
```bash
|
||||
API=https://manga-api.violetcrown.my.id
|
||||
WEB=https://manga.violetcrown.my.id
|
||||
API=https://bookmark-api.violetcrown.my.id
|
||||
WEB=https://bookmark.violetcrown.my.id
|
||||
TOKEN=$(grep -E '^API_TOKEN=' .env | cut -d= -f2)
|
||||
|
||||
curl -s $API/healthz # -> ok
|
||||
@@ -281,7 +281,7 @@ docker run --rm -v "$VOL":/data -v "$BACKUP_DIR":/backup alpine sh -c '
|
||||
ls -l /data'
|
||||
|
||||
$COMPOSE start
|
||||
docker logs manga-api --tail 20
|
||||
docker logs bookmark-api --tail 20
|
||||
curl -s -H "Authorization: Bearer $TOKEN" $API/bookmarks | head -c 200
|
||||
```
|
||||
|
||||
@@ -302,9 +302,9 @@ Two steps here are easy to skip and both bite:
|
||||
For a routine redeploy where nothing needs deciding:
|
||||
|
||||
```bash
|
||||
cd /opt/mangabm
|
||||
cd /opt/bookmarkmanager
|
||||
COMPOSE="docker compose -f docker-compose.yml -f docker-compose.prod.yml"
|
||||
BACKUP_DIR="$(cd .. && pwd)/mangabm-backups"; mkdir -p "$BACKUP_DIR"
|
||||
BACKUP_DIR="$(cd .. && pwd)/bookmarkmanager-backups"; mkdir -p "$BACKUP_DIR"
|
||||
VOL=$(docker volume ls --filter name=bookmarks-data -q | head -1)
|
||||
STAMP=$(date -u +%Y%m%d-%H%M%S)
|
||||
|
||||
@@ -314,7 +314,7 @@ docker run --rm -v "$VOL":/data -v "$BACKUP_DIR":/backup alpine sh -c \
|
||||
git pull --ff-only &&
|
||||
$COMPOSE up -d --build &&
|
||||
sleep 5 &&
|
||||
curl -sf https://manga-api.violetcrown.my.id/healthz && echo " deploy ok"
|
||||
curl -sf https://bookmark-api.violetcrown.my.id/healthz && echo " deploy ok"
|
||||
```
|
||||
|
||||
The `&&` chain is deliberate: if the backup or its integrity check fails,
|
||||
@@ -332,7 +332,7 @@ command can tell you the panel works on the phone.
|
||||
| CSS or template change did not appear | You restarted without `--build`. Assets are `//go:embed`ed. |
|
||||
| Font answers `application/octet-stream` | Old binary — the `.woff2` MIME registration is in `web.go`. Rebuild. |
|
||||
| Everyone logged out of the web UI | `API_TOKEN` or `WEB_PASSWORD` changed; sessions are derived from both. Expected, just log in again. |
|
||||
| `compose` errors about `MANGA_WEB_HOST` | Run from the directory holding `.env`. Both host vars are required even when the web UI is unused. |
|
||||
| `compose` errors about `BOOKMARK_WEB_HOST` | Run from the directory holding `.env`. Both host vars are required even when the web UI is unused. |
|
||||
| Userscript did not update on the phone | Violentmonkey polls on its own schedule; force a check. `@version` comes from the file's mtime, so confirm the pull actually touched it. |
|
||||
| `apk add sqlite` fails (no network) | Use the cold-copy fallback in §1 — and copy `bookmarks.db-wal` too. |
|
||||
| Reads work but every write fails after a restore | Restored file is root-owned; the container is uid 65532. `chown 65532:65532` it (§6). |
|
||||
|
||||
Reference in New Issue
Block a user