docs+ci: folder import stays retired, and fix a readiness probe that never probed
CI / lint (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
CI / extension-version (push) Successful in 3s
Build images / build-ml (push) Successful in 7s
Build images / build-agent (push) Successful in 13s
Build images / build-web (push) Successful in 7s
CI / frontend-build (push) Successful in 22s
extension / lint (push) Successful in 29s
CI / backend-lint-and-test (push) Successful in 49s
CI / integration (push) Successful in 1m57s
extension / lint (pull_request) Successful in 22s
CI / lint (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
CI / extension-version (push) Successful in 3s
Build images / build-ml (push) Successful in 7s
Build images / build-agent (push) Successful in 13s
Build images / build-web (push) Successful in 7s
CI / frontend-build (push) Successful in 22s
extension / lint (push) Successful in 29s
CI / backend-lint-and-test (push) Successful in 49s
CI / integration (push) Successful in 1m57s
extension / lint (pull_request) Successful in 22s
Two unrelated things, both found while closing out milestone 328. **Folder import (#3367).** The operator's call, this session: the import-from-file surface was abandoned on purpose and is not coming back — "it has its own complexities that we didn't need." The README and the compose comment both described the missing button as a rough edge with a tracking issue, which promised a fix that is not coming. Both now say the retirement is the decision, name Subscriptions as the supported way to fill a new install, and describe /api/import/trigger as an unsupported escape hatch for anyone who wants to script one. **The CI readiness probe.** ci.yml's integration job and baseline.yml both waited for Postgres with `(echo > /dev/tcp/$PG_IP/5432)`. Those steps run under `sh -e` — act's default shell — where /dev/tcp is not a magic path but a filename that does not exist. The probe could therefore never succeed: run 18035, a GREEN run, spends 05:20:53 → 05:22:53 in that loop and exits it by exhaustion, not by connecting. Every integration run has been paying a flat 120s for a check that established nothing, and proceeding regardless. Replaced with a socket connect in python (present in the image, no package needed), and exhausting the budget is now a named failure instead of a silent fall-through — rule 156. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTjbZZ6JirCMSaJzQV1RhA
This commit is contained in:
@@ -87,10 +87,21 @@ jobs:
|
|||||||
test -n "$PG_IP"
|
test -n "$PG_IP"
|
||||||
echo "PG_CONTAINER=$PG" >> "$GITHUB_ENV"
|
echo "PG_CONTAINER=$PG" >> "$GITHUB_ENV"
|
||||||
echo "DB_HOST=$PG_IP" >> "$GITHUB_ENV"
|
echo "DB_HOST=$PG_IP" >> "$GITHUB_ENV"
|
||||||
|
# Socket probe in python, not bash's /dev/tcp — these steps run under
|
||||||
|
# `sh -e`, where that path does not exist. Same fix and same reasoning
|
||||||
|
# as ci.yml's integration job; see the comment there.
|
||||||
|
pg_ready=""
|
||||||
for i in $(seq 1 60); do
|
for i in $(seq 1 60); do
|
||||||
(echo > "/dev/tcp/$PG_IP/5432") >/dev/null 2>&1 && break
|
if python -c "import socket,sys; s=socket.socket(); s.settimeout(2); sys.exit(0 if s.connect_ex(('$PG_IP', 5432)) == 0 else 1)"; then
|
||||||
|
pg_ready=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
if [ -z "$pg_ready" ]; then
|
||||||
|
echo "postgres at $PG_IP:5432 did not accept a connection within 120s"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if command -v uv >/dev/null 2>&1; then
|
if command -v uv >/dev/null 2>&1; then
|
||||||
uv pip install --system -r requirements.txt
|
uv pip install --system -r requirements.txt
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -255,10 +255,27 @@ jobs:
|
|||||||
export DB_HOST="$PG_IP"
|
export DB_HOST="$PG_IP"
|
||||||
export CELERY_BROKER_URL="redis://$RD_IP:6379/0"
|
export CELERY_BROKER_URL="redis://$RD_IP:6379/0"
|
||||||
export CELERY_RESULT_BACKEND="redis://$RD_IP:6379/0"
|
export CELERY_RESULT_BACKEND="redis://$RD_IP:6379/0"
|
||||||
|
# These steps run under `sh -e`, not bash, so bash's /dev/tcp magic
|
||||||
|
# path does not exist here — the probe this loop used to run could
|
||||||
|
# never succeed and simply burned the full 120s on every run, green
|
||||||
|
# or red, then continued without having established anything. Python
|
||||||
|
# is in the image and needs no installed package for a socket
|
||||||
|
# connect, so it is the probe. Exhausting the budget is now a named
|
||||||
|
# failure rather than a silent fall-through (rule 156): if Postgres
|
||||||
|
# is genuinely not up, that is what the log should say, instead of
|
||||||
|
# whatever the first query happens to raise two minutes later.
|
||||||
|
pg_ready=""
|
||||||
for i in $(seq 1 60); do
|
for i in $(seq 1 60); do
|
||||||
(echo > "/dev/tcp/$PG_IP/5432") >/dev/null 2>&1 && break
|
if python -c "import socket,sys; s=socket.socket(); s.settimeout(2); sys.exit(0 if s.connect_ex(('$PG_IP', 5432)) == 0 else 1)"; then
|
||||||
|
pg_ready=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
if [ -z "$pg_ready" ]; then
|
||||||
|
echo "postgres at $PG_IP:5432 did not accept a connection within 120s"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if command -v uv >/dev/null 2>&1; then
|
if command -v uv >/dev/null 2>&1; then
|
||||||
uv pip install --system -r requirements.txt pytest pytest-asyncio
|
uv pip install --system -r requirements.txt pytest pytest-asyncio
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -94,17 +94,19 @@ A few things are worth knowing about the first few minutes:
|
|||||||
than broken. It is idempotent — a restart resumes rather than refetches.
|
than broken. It is idempotent — a restart resumes rather than refetches.
|
||||||
- **The gallery starts empty**, and that is the expected state. Add a creator
|
- **The gallery starts empty**, and that is the expected state. Add a creator
|
||||||
under **Subscriptions** and it fills as posts come down.
|
under **Subscriptions** and it fills as posts come down.
|
||||||
- **If you already have a library on disk**, note that importing it is
|
- **If you already have a library on disk**, there is no screen that imports
|
||||||
currently an API call rather than a button — the manual-scan UI was retired
|
it, and there is not going to be one. Folder ingestion had a UI until July
|
||||||
in July 2026, when imports started arriving entirely via downloads and the
|
2026; it was retired once posts began arriving entirely through
|
||||||
extension. Mount the folder at `./import` and kick it off with:
|
subscriptions and the browser extension, and the decision to leave it
|
||||||
|
retired is deliberate — the folder path carries complexity the product does
|
||||||
|
not need in order to do its job. The supported way to fill a new install is
|
||||||
|
to add the creators you follow under **Subscriptions** and let it pull.
|
||||||
|
|
||||||
```bash
|
The `/api/import/trigger` endpoint is still wired up for anyone who wants to
|
||||||
curl -X POST http://localhost:8080/api/import/trigger
|
script a one-off against a folder mounted at `./import`, and its progress
|
||||||
```
|
shows under **Settings → Activity**. Treat it as an unsupported escape
|
||||||
|
hatch rather than a feature: nothing in the UI drives it and nothing else
|
||||||
Progress shows up under **Settings → Activity**. This is a known rough
|
in this README depends on it.
|
||||||
edge, not the intended shape (#3367).
|
|
||||||
- **To download from a paywalled account**, FabledCurator needs that account's
|
- **To download from a paywalled account**, FabledCurator needs that account's
|
||||||
session — see the browser extension below. Without one it can still fetch
|
session — see the browser extension below. Without one it can still fetch
|
||||||
public posts.
|
public posts.
|
||||||
|
|||||||
+8
-6
@@ -136,9 +136,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./images:/images
|
- ./images:/images
|
||||||
- ./import:/import
|
- ./import:/import
|
||||||
# /import is the staging area for ingesting a library you already have
|
# /import is a staging area for scripting a one-off ingest of a library
|
||||||
# on disk. Drop files in ./import, or bind-mount an existing directory
|
# you already have on disk. Drop files in ./import, or bind-mount an
|
||||||
# under it as below, then trigger the scan:
|
# existing directory under it as below, then trigger the scan:
|
||||||
#
|
#
|
||||||
# curl -X POST http://localhost:8080/api/import/trigger
|
# curl -X POST http://localhost:8080/api/import/trigger
|
||||||
#
|
#
|
||||||
@@ -146,9 +146,11 @@ services:
|
|||||||
# worker + scheduler services mount the same /import so the scan can run
|
# worker + scheduler services mount the same /import so the scan can run
|
||||||
# on whichever lane picks it up.
|
# on whichever lane picks it up.
|
||||||
#
|
#
|
||||||
# There is no UI button for this: the manual-scan surface was retired
|
# Deliberately has no UI. The manual-scan surface was retired 2026-07-02
|
||||||
# 2026-07-02 once imports arrived via downloads + the extension, which is
|
# once imports arrived via subscriptions + the extension, and the call
|
||||||
# true for an established install and not for a new one. Tracked in #3367.
|
# not to restore it stands (operator, 2026-09-02): folder ingestion
|
||||||
|
# brings complexity the product does not need. The endpoint stays as an
|
||||||
|
# unsupported escape hatch; the supported way in is Subscriptions.
|
||||||
# - /srv/media/my-library:/import/my-library:ro
|
# - /srv/media/my-library:/import/my-library:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres: { condition: service_healthy }
|
postgres: { condition: service_healthy }
|
||||||
|
|||||||
Reference in New Issue
Block a user