36cc062 fix(importer): sanitize PostAttachment.ext — gallery-dl produces filenames with URL-encoded basenames like ...https___www.patreon.com_media-u_Z0FBQUFBQm5q...; Path.suffix on those returns 50+ chars of base64-ish junk and blew the ext varchar(32) column, killing the import worker. New _safe_ext() helper returns empty string for anything >16 chars or containing non-alphanumeric characters; bounded column stays as load-bearing safety net. Pinned by test_mangled_filename_extension_is_sanitized. Worker-blocking; this is the priority change in the release.
3531f37 feat(settings): move BrowserExtensionCard from Maintenance to Overview — Overview is the discovery surface for "things to set up"; Maintenance is for housekeeping of already-set-up systems.
e50f92d perf(ci): shard integration suite into 3 parallel jobs — newly feasible after act_runner capacity bump 2→6. intapi (tests/test_api_*.py), intimp (importer/migration/phash/sidecar/scan), intcore (everything else). Each shard gets its own postgres+redis service containers and runs alembic + a disjoint subset of integration tests. Approximate split — rebalance once --durations=15 output reveals which shard is the long pole.
ac39509 fix(ci): rename shard jobs to no-separator names + add diagnostic dump — first push used int_api/int_imp/int_core but act_runner sanitizes underscores in container-name labels, so the docker-ps filter found zero matches. No-separator names work, and a docker ps -a --format dump runs first now so any future naming-convention shift surfaces in the log without another guess-and-push cycle.
ba8d9b1 fix(ext-ci): diagnostic tracing on commit step — adds set -x + targeted echos so the next extension workflow run on main reveals why run #309 reported success without producing the ext: publish signed XPI side-commit. Only fires when the workflow runs on main (sign-and-publish is main-gated).
Notes on the extension publish
This PR doesn't include the bundled XPI (the side-commit didn't land last cycle). After merge, the extension workflow will self-retrigger on main (path filter includes .forgejo/workflows/extension.yml); the diagnostic dump in ba8d9b1 should explain the previous run's silent no-commit outcome. Release tag timing for v26.05.25.4: cut immediately after merge so the ext fix ships fast; the XPI side-commit (if it actually lands this time) gets picked up by the next image build organically.
## Summary
Five commits on dev:
- **`36cc062` fix(importer): sanitize PostAttachment.ext** — gallery-dl produces filenames with URL-encoded basenames like `...https___www.patreon.com_media-u_Z0FBQUFBQm5q...`; `Path.suffix` on those returns 50+ chars of base64-ish junk and blew the `ext varchar(32)` column, killing the import worker. New `_safe_ext()` helper returns empty string for anything >16 chars or containing non-alphanumeric characters; bounded column stays as load-bearing safety net. Pinned by `test_mangled_filename_extension_is_sanitized`. **Worker-blocking; this is the priority change in the release.**
- **`3531f37` feat(settings): move BrowserExtensionCard from Maintenance to Overview** — Overview is the discovery surface for "things to set up"; Maintenance is for housekeeping of already-set-up systems.
- **`e50f92d` perf(ci): shard integration suite into 3 parallel jobs** — newly feasible after act_runner capacity bump 2→6. `intapi` (tests/test_api_*.py), `intimp` (importer/migration/phash/sidecar/scan), `intcore` (everything else). Each shard gets its own postgres+redis service containers and runs alembic + a disjoint subset of integration tests. Approximate split — rebalance once `--durations=15` output reveals which shard is the long pole.
- **`ac39509` fix(ci): rename shard jobs to no-separator names + add diagnostic dump** — first push used `int_api`/`int_imp`/`int_core` but act_runner sanitizes underscores in container-name labels, so the docker-ps filter found zero matches. No-separator names work, and a `docker ps -a --format` dump runs first now so any future naming-convention shift surfaces in the log without another guess-and-push cycle.
- **`ba8d9b1` fix(ext-ci): diagnostic tracing on commit step** — adds `set -x` + targeted echos so the next extension workflow run on main reveals why run #309 reported success without producing the `ext: publish signed XPI` side-commit. Only fires when the workflow runs on main (sign-and-publish is main-gated).
## Notes on the extension publish
This PR doesn't include the bundled XPI (the side-commit didn't land last cycle). After merge, the extension workflow will self-retrigger on main (path filter includes `.forgejo/workflows/extension.yml`); the diagnostic dump in `ba8d9b1` should explain the previous run's silent no-commit outcome. Release tag timing for v26.05.25.4: cut immediately after merge so the ext fix ships fast; the XPI side-commit (if it actually lands this time) gets picked up by the next image build organically.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Five commits on dev:
36cc062fix(importer): sanitize PostAttachment.ext — gallery-dl produces filenames with URL-encoded basenames like...https___www.patreon.com_media-u_Z0FBQUFBQm5q...;Path.suffixon those returns 50+ chars of base64-ish junk and blew theext varchar(32)column, killing the import worker. New_safe_ext()helper returns empty string for anything >16 chars or containing non-alphanumeric characters; bounded column stays as load-bearing safety net. Pinned bytest_mangled_filename_extension_is_sanitized. Worker-blocking; this is the priority change in the release.3531f37feat(settings): move BrowserExtensionCard from Maintenance to Overview — Overview is the discovery surface for "things to set up"; Maintenance is for housekeeping of already-set-up systems.e50f92dperf(ci): shard integration suite into 3 parallel jobs — newly feasible after act_runner capacity bump 2→6.intapi(tests/test_api_*.py),intimp(importer/migration/phash/sidecar/scan),intcore(everything else). Each shard gets its own postgres+redis service containers and runs alembic + a disjoint subset of integration tests. Approximate split — rebalance once--durations=15output reveals which shard is the long pole.ac39509fix(ci): rename shard jobs to no-separator names + add diagnostic dump — first push usedint_api/int_imp/int_corebut act_runner sanitizes underscores in container-name labels, so the docker-ps filter found zero matches. No-separator names work, and adocker ps -a --formatdump runs first now so any future naming-convention shift surfaces in the log without another guess-and-push cycle.ba8d9b1fix(ext-ci): diagnostic tracing on commit step — addsset -x+ targeted echos so the next extension workflow run on main reveals why run #309 reported success without producing theext: publish signed XPIside-commit. Only fires when the workflow runs on main (sign-and-publish is main-gated).Notes on the extension publish
This PR doesn't include the bundled XPI (the side-commit didn't land last cycle). After merge, the extension workflow will self-retrigger on main (path filter includes
.forgejo/workflows/extension.yml); the diagnostic dump inba8d9b1should explain the previous run's silent no-commit outcome. Release tag timing for v26.05.25.4: cut immediately after merge so the ext fix ships fast; the XPI side-commit (if it actually lands this time) gets picked up by the next image build organically.🤖 Generated with Claude Code