mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-10 11:47:52 +02:00
✅(collaboration) test the legacy migrations against a real yhub
Cover both paths off the legacy Django store end to end: the lazy seed on
first access, and the migrate endpoint replaying every S3 version. The tests
need no database — the admin JWT short-circuits document authorization, so a
fixture is an S3 object on a random uuid — and read the timeline through
yhub 0.5.0's `Accept: application/json`, which spares python a lib0 decoder.
CI grows a valkey service and starts a collaboration server alongside the
backend test job; the tests skip themselves when nothing answers on the new
COLLABORATION_API_URL setting, so `make test` without the dev stack still
passes.
Writing them turned up three things worth fixing in the server.
Backend reads now seed too. getAccessType short-circuited on the admin token
before reaching the legacy store, so a server-side read of an unmigrated
document answered with an empty one, and a create-ydoc against it would have
written a second lineage beside the content the first user access was about
to seed in.
Seeding no longer decides access; the backend's answer alone does. A legacy
object that cannot be migrated — it does not decode, or it exceeds the size
we load — opens as a new document instead of denying, since no retry can fix
it and refusing would leave the document unopenable by anyone. The cause is
logged once per attempt with the bucket, key and stack, and every later access
logs that it admitted a caller without migrating.
That made the failure classifier dangerous, so it is inverted. It was an
allowlist of retryable errors — eight socket errnos — which left every way S3
can refuse (AccessDenied on a rotated key, NoSuchBucket, a region redirect)
counting as "this object is unusable". Denying, that was survivable; opening
empty, one misscoped credential would fork every document touched during the
window. Now only a failure raised while interpreting bytes we already hold is
permanent, marked at the throw site, and everything else answers a retryable
503. Guessing wrong that way costs a retry; the other way costs the document.
The admin seed is also fenced to the org and to main, like the user path
above it. The legacy store is branchless — {docid}/file is main — and the
bookkeeping is per document, so seeding ?branch=draft would have written
main's content into an orphan room and left the real one permanently empty.
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
This commit is contained in:
@@ -128,6 +128,13 @@ jobs:
|
||||
# needed because the postgres container does not provide a healthcheck
|
||||
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||
|
||||
# message stream for the collaboration server (see the yhub steps below)
|
||||
valkey:
|
||||
image: valkey/valkey:alpine
|
||||
ports:
|
||||
- 6379:6379
|
||||
options: --health-cmd "valkey-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
||||
|
||||
env:
|
||||
DJANGO_CONFIGURATION: Test
|
||||
DJANGO_SETTINGS_MODULE: impress.settings
|
||||
@@ -142,6 +149,12 @@ jobs:
|
||||
AWS_S3_ENDPOINT_URL: http://localhost:9000
|
||||
AWS_S3_ACCESS_KEY_ID: impress
|
||||
AWS_S3_SECRET_ACCESS_KEY: password
|
||||
# Collaboration server. The integration tests reach it over this url and
|
||||
# skip themselves when nothing answers; yhub reads the JWKS back from the
|
||||
# django server started alongside it, so both sides must share
|
||||
# JWT_PRIVATE_KEY_FILE.
|
||||
COLLABORATION_API_URL: http://localhost:3002/collaboration
|
||||
JWT_PRIVATE_KEY_FILE: ${{ github.workspace }}/data/jwt/private.pem
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -203,8 +216,61 @@ jobs:
|
||||
sudo apt-get install -y gettext pandoc shared-mime-info
|
||||
sudo wget https://raw.githubusercontent.com/suitenumerique/django-lasuite/refs/heads/main/assets/conf/mime.types -O /etc/mime.types
|
||||
|
||||
# --- collaboration server -------------------------------------------
|
||||
# The yhub integration tests drive a real collaboration server: it reads
|
||||
# legacy documents out of MinIO and reads this backend's JWKS back to
|
||||
# verify the admin token the tests mint, so the two must share the
|
||||
# signing key. Tests skip themselves when nothing answers on
|
||||
# COLLABORATION_API_URL.
|
||||
- name: Generate the JWT signing key
|
||||
working-directory: .
|
||||
run: bin/generate-jwt-private-key.sh
|
||||
|
||||
- name: Create the collaboration server database
|
||||
run: |
|
||||
PGPASSWORD=pass psql -h localhost -U dinum -d impress \
|
||||
-c 'CREATE DATABASE yhub'
|
||||
PGPASSWORD=pass psql -h localhost -U dinum -d yhub \
|
||||
-f ../../docker/files/yhub/initdb/01-yhub.sql
|
||||
|
||||
- name: Generate a MO file from strings extracted from the project
|
||||
run: uv run python manage.py compilemessages
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: "22.x"
|
||||
|
||||
- name: Install the collaboration server
|
||||
working-directory: src/yhub-server
|
||||
run: npm ci --omit=dev
|
||||
|
||||
- name: Start the backend for the collaboration server to authenticate against
|
||||
env:
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
run: |
|
||||
nohup uv run python manage.py runserver 0.0.0.0:8000 --noreload \
|
||||
> /tmp/backend.log 2>&1 &
|
||||
dockerize -wait http://localhost:8000/api/v1.0/jwks -timeout 60s
|
||||
|
||||
- name: Start the collaboration server
|
||||
working-directory: src/yhub-server
|
||||
env:
|
||||
PORT: 3002
|
||||
REDIS: redis://localhost:6379
|
||||
POSTGRES: postgres://dinum:pass@localhost:5432/yhub
|
||||
REDIS_PREFIX: yhub
|
||||
COLLABORATION_BACKEND_BASE_URL: http://localhost:8000
|
||||
COLLABORATION_SERVER_ORIGIN: http://localhost:3000
|
||||
AWS_STORAGE_BUCKET_NAME: impress-media-storage
|
||||
SOFT_MIGRATION: "true"
|
||||
run: |
|
||||
nohup node server.js > /tmp/yhub.log 2>&1 &
|
||||
dockerize -wait tcp://localhost:3002 -timeout 30s
|
||||
|
||||
- name: Run tests
|
||||
run: uv run pytest -n 2
|
||||
|
||||
- name: Collaboration server logs
|
||||
if: failure()
|
||||
run: cat /tmp/yhub.log /tmp/backend.log
|
||||
|
||||
Reference in New Issue
Block a user