Files
zkldi_Tachi/Justfile-test
T
zk ae5e72aa89 fix: resize profile images on upload and cache redirect responses (#1564)
* fix: resize profile images on upload and add cache headers

Profile pictures were stored at original upload size (up to 1 MB) but
only ever displayed at 32–128 px, so every page load downloaded the full
original image. Additionally, no Cache-Control headers were set anywhere
in the pipeline, forcing a fresh round-trip through the API redirect and
CDN on every page view.

- Resize JPEG/PNG pfps to max 256×256 and banners to max 1920×1080 via
  sharp before storing; re-encode to WebP at 85% quality (GIFs skipped
  to preserve the animated-GIF easter egg)
- Hash the resized buffer so the CDN path reflects what's on disk
- Set ContentType and CacheControl: immutable on S3 PutObject so CDN
  edges and browsers cache the objects indefinitely (safe because paths
  are content-addressed via SHA-256)
- Add Cache-Control: public, max-age=3600, stale-while-revalidate=86400
  to the GET /pfp and GET /banner redirect responses so browsers cache
  the userId→CDN-URL mapping and skip the API hop on repeat visits

Fixes #1553

* chore: apply biome formatting

* chore: generate ImportTimestop kanel type

* feat: add backfill-media script to migrate existing profile images

One-off script that reads every user's existing pfp and banner from S3,
runs them through the same sharp resize/WebP pipeline as new uploads,
stores the result under the new content-addressed key with immutable
cache headers, and updates custom_pfp_location/custom_banner_location
in the DB.

Features:
- --dry-run flag to preview changes without writing anything
- Skips objects already at optimal size (idempotent)
- Gracefully handles missing S3 objects (logs + skips)
- Summary stats at the end
- Reads S3 config from CLI args or TACHI_CDN_SAVE_LOCATION_* env vars

* chore: apply biome formatting to backfill-media

* fix: resize animated GIFs to animated WebP via sharp animated:true

* test: rewrite change-pfp/banner tests as real S3 + sharp integration

Remove the CDN mock entirely. Tests now pass real image buffers through
sharp and verify the stored S3 object via CDNRetrieve:

- PNG/JPEG input → assert stored object is WebP, dimensions ≤256×256,
  smaller than the original
- GIF input → assert stored object is WebP
- Hash returned from the action == SHA256 of the stored WebP bytes
  (not the original upload)
- Delete tests upload a real pfp then delete it and verify CDNRetrieve
  throws afterwards

Also move change-pfp.test.ts from the isolated vitest project back to
the default pool now that it no longer uses vi.mock.

* chore: apply biome formatting to test file

* fix: use POSTGRES_TEST_HOST env var in bot vitest setup

Both vitest.globalSetup.ts and vitest.setup.ts hardcoded 'tachi-postgres'
(the dev server), but just bot-db-test-template-reset creates the template
on 'tachi-postgres-test' (the tmpfs test server). Workers then failed to
clone the template because they were looking on the wrong host.

Mirrors the pattern already used in the server package:
  process.env.POSTGRES_TEST_HOST ?? 'tachi-postgres-test'

* fix: update pfp router tests for WebP resize pipeline

The PUT tests were comparing the stored S3 bytes directly to the original
upload buffer. Since we now resize and re-encode to WebP, this always
fails. Also, following the mockApi redirect to fetch the bytes added a
slow supertest round-trip.

Replace with: read custom_pfp_location from the DB after PUT, fetch the
stored object directly via CDNRetrieve, and assert it is smaller than the
original (non-deterministic WebP compression makes exact byte comparison
inappropriate).

* fix: update banner router tests for WebP resize pipeline

* fix: tests

* fix: ci
2026-05-23 13:48:49 +01:00

121 lines
3.4 KiB
Plaintext

check:
#!/bin/bash
set -euo pipefail
source .scripts/multi_evaluator.sh
evaluate "just fmt-check"
evaluate "bun run --filter '*' lint -- --quiet"
evaluate "just typecheck"
evaluate "bun .scripts/ts_machete.js"
evaluate "bun .scripts/ts_autoinherit.js --check"
post_evaluate
typecheck:
bun run --elide-lines=0 --filter '!tachi-seeds-scripts' typecheck
typecheck-sequential:
bun run --elide-lines=0 --filter '!tachi-seeds-scripts' typecheck
fix:
#!/bin/bash
set -euo pipefail
just gen
bun run --elide-lines=0 --filter '*' lint-fix -- --quiet
.scripts/ts_autoinherit.js
just fmt
# Automatically fix any issues we can in the codebase and then
# make a commit for them
autofix:
#!/bin/bash
set -euo pipefail
# Only generate a commit if the repo is clean
SHOULD_COMMIT=0
if [ -z "$(git status --porcelain)" ]; then
SHOULD_COMMIT=1
fi
just fix
if [ $SHOULD_COMMIT -eq 1 ]; then
git add .
git commit -m "chore: autofix"
fi
fmt:
bun biome format --write
bun prettier --write --list-different .
fmt-check:
bun biome format
bun prettier --check .
test FILTER="*":
#!/bin/bash
set -euo pipefail
source .scripts/multi_evaluator.sh
evaluate "just test-typescript '{{FILTER}}'"
post_evaluate
test-typescript FILTER="*":
#!/bin/bash
set -euo pipefail
export POSTGRES_TEST_HOST="tachi-postgres-test"
export POSTGRES_TEST_URL="postgresql://tachi:tachi@${POSTGRES_TEST_HOST}"
bun run --elide-lines=0 --sequential --filter '{{FILTER}}' test -- --reporter=default --reporter=junit --outputFile.junit=test-results/junit.xml
# Summarize Vitest v8 coverage across workspaces (see typescript/coverage-tools).
coverage-report *ARGS:
bun run --filter tachi-coverage-tools report -- {{ARGS}}
# Run all parity suites, or a single one if a name is given.
test-parity suite="":
TACHI_SERVER=https://localhost:8080 bun vitest run {{ if suite != "" { "tests/" + suite + ".test.ts" } else { "" } }}
# ==> Orchestration of parallel db tests
# Create (or recreate) the bot test template database with all migrations applied.
# Workers clone from this template rather than re-running migrations each time.
# Targets the dedicated tmpfs `tachi-postgres-test` server (override via
# POSTGRES_TEST_URL).
bot-db-test-template-reset:
#!/bin/bash
set -euo pipefail
export POSTGRES_URL="{{POSTGRES_TEST_URL}}/tachi_bot_test_template"
tachidb database drop
tachidb database create
tachidb migrate run
# Create (or recreate) the server test template database with all migrations applied.
# Workers clone from this template rather than re-running migrations each time.
# Targets the dedicated tmpfs `tachi-postgres-test` server (override via
# POSTGRES_TEST_URL).
server-db-test-template-reset:
#!/bin/bash
set -euo pipefail
export POSTGRES_URL="{{POSTGRES_TEST_URL}}/tachi_server_test_template"
tachidb database drop
tachidb database create
tachidb migrate run
# <== End of parallel db test justscripts
# Score-import HTTP load tests against a live server (multipart /api/v1/import/file).
# See typescript/server/src/load-tests/README.md
load-test-score-import *ARGS:
cd typescript/server && bun run load-test:score-import -- {{ARGS}}
# Seed N dev users + API tokens (submit_score); writes one token per line to OUTPUT_FILE.
# Uses the server package env (.env); same Postgres as a local tachi-server.
load-test-score-import-seed-tokens COUNT OUTPUT_FILE:
cd typescript/server && bun run src/load-tests/seed-stress-api-tokens.ts {{COUNT}} {{OUTPUT_FILE}}