# End-to-end test stack — used by .gitea/workflows/e2e.yml and by # operators who want to run the Playwright suite locally. # # Three services: # * server — restic-manager built from the working tree # * agent — restic-manager agent built from the working tree # (announces; Playwright accepts it during the test) # * rest-server — the actual restic backend, sibling of the agent # # Run from the repo root: # docker compose -f e2e/compose.e2e.yml up --build --abort-on-container-exit services: rest-server: image: restic/rest-server:0.13.0 environment: DATA_DIR: /data OPTIONS: "--no-auth" volumes: - rest-data:/data networks: [rmnet] server: build: context: .. dockerfile: deploy/Dockerfile.server args: VERSION: e2e environment: RM_LISTEN: ":8080" RM_DATA_DIR: "/data" RM_BASE_URL: "http://server:8080" RM_COOKIE_SECURE: "false" # Bind the metrics endpoint loose for the test, so one of the # Playwright assertions can exercise it. RM_METRICS_TRUSTED_CIDR: "0.0.0.0/0" volumes: - server-data:/data ports: - "127.0.0.1:8080:8080" healthcheck: test: ["CMD", "/usr/local/bin/restic-manager-server", "--version"] interval: 2s timeout: 2s retries: 30 networks: [rmnet] agent: build: context: .. dockerfile: e2e/Dockerfile.agent args: VERSION: e2e environment: RM_SERVER: "http://server:8080" depends_on: - server volumes: # Source paths the agent backs up. Compose pre-populates this # with a few files so the snapshot list isn't empty. - source-data:/source - agent-config:/etc/restic-manager - agent-state:/var/lib/restic-manager-agent networks: [rmnet] # Playwright test runner. Profile-gated so `compose up` doesn't # start it; CI invokes it via `compose run` and `docker cp`s the # report+traces out (see .gitea/workflows/e2e.yml). Lives on # rmnet so it can reach the server via its compose-network DNS # name rather than depending on host port-publish (which doesn't # work on Gitea's container-based runners). # # Reports are NOT bind-mounted: when the runner job itself runs # inside a container, `./playwright/...` resolves to a path that # only exists inside the runner container, so the host docker # daemon would silently mount an empty dir. Instead the report # stays inside the playwright container and the workflow extracts # it via `docker cp` before tearing down. playwright: profiles: [test] build: context: .. dockerfile: e2e/Dockerfile.playwright environment: RM_BASE_URL: "http://server:8080" RM_BOOTSTRAP_TOKEN: "${RM_BOOTSTRAP_TOKEN:-}" depends_on: - server - agent networks: [rmnet] # One-shot init container that drops a couple of files into the # source volume so backups have something to snapshot. source-fixture: image: alpine:3.20 command: > sh -c 'mkdir -p /source && echo "hello world" > /source/hello.txt && echo "another file" > /source/two.txt && sleep 0.2' volumes: - source-data:/source networks: [rmnet] restart: "no" volumes: server-data: rest-data: source-data: agent-config: agent-state: networks: rmnet: driver: bridge