When a CI build fails, start by identifying the failing step:
curl -s "http://ci.syncloud.org:8080/api/repos/syncloud/redirect/builds/{N}" | python3 -c "
import json,sys
b=json.load(sys.stdin)
for stage in b.get('stages', []):
for step in stage.get('steps', []):
if step.get('status') == 'failure':
print(f\"stage {stage.get('number')} step {step.get('number')}: {step.get('name')}\")
"Get the log for a specific stage/step:
curl -s "http://ci.syncloud.org:8080/api/repos/syncloud/redirect/builds/{N}/logs/{stage}/{step}" | python3 -c "
import json,sys
for line in json.load(sys.stdin):
print(line.get('out', ''), end='')
" | tail -120Example from build 1216:
- failing pipeline:
redirect-amd64 - failing step:
stage 1 step 6 - failure reason: Jest picked up
www/e2e/*.spec.jsand executed Playwright files duringnpm run test
Web UI:
http://ci.syncloud.org:8080/syncloud/redirect
Drone API examples:
curl -s "http://ci.syncloud.org:8080/api/repos/syncloud/redirect/builds?limit=5"
curl -s "http://ci.syncloud.org:8080/api/repos/syncloud/redirect/builds/{N}"
curl -s "http://ci.syncloud.org:8080/api/repos/syncloud/redirect/builds/{N}/logs/{stage}/{step}"The main repo pipeline currently does:
build webRunsnpm install,npm run test,npm run lint,npm run buildbuild backendpackagetest-integrationtest-ui-playwrightartifact
The UI test migration separates test runners:
npm run test= Jest unit tests onlynpm run test:e2e= Playwright end-to-end tests only
If Jest starts executing www/e2e/*.spec.js, CI will fail before Playwright even starts.
Keep www/jest.config.js ignoring e2e/.
Prefer data-testid over role/text locators for anything asserted or clicked in a Playwright test. When a new element needs to be targeted by a test, add a data-testid="..." attribute to the Vue template and use page.getByTestId(...) in the spec.
Why:
- Role + accessible-name matching is a partial-match by default and breaks when another element on the page contains the same text (e.g.
AccountvsDelete this account). - Text matching couples tests to copy changes and translations.
data-testidis stable, explicit, and survives refactors of DOM structure.
Use role/text locators only for elements genuinely verified as user-facing semantics (e.g. asserting a button literally reads "Confirm"), not as the primary hook.
Playwright tests live in:
www/e2e/
Configuration:
www/playwright.config.js
Current intent:
- shared
*.spec.jsflows run on bothdesktopandmobile *.mobile.spec.jsholds mobile-only assertions- screenshots are taken explicitly on failure in
www/e2e/fixtures.js - videos are retained in
www/test-results
The layout is:
- full desktop run (
test-ui-desktopin Drone) - full mobile run (
test-ui-mobilein Drone) - extra mobile-specific checks where needed
Artifacts are uploaded by the artifact step and served by an nginx file browser at http://ci.syncloud.org:8081.
List build artifacts:
curl -s "http://ci.syncloud.org:8081/files/redirect/{N}/"Typical layout for a redirect build:
{N}/
redirect-{N}.tar.gz
distro/
playwright-report/
playwright-results/
<test-slug>/
error-context.md
failure-full-page.png
trace.zip
video.webm
Fetch a Playwright failure's page snapshot + error:
curl -s "http://ci.syncloud.org:8081/files/redirect/{N}/playwright-results/<slug>/error-context.md"Download the trace and inspect URLs or network calls locally:
curl -O "http://ci.syncloud.org:8081/files/redirect/{N}/playwright-results/<slug>/trace.zip"
unzip -q trace.zip -d trace/
grep -oE "/some-path\?[^\" ]*" trace/0-trace.trace | headThose directories are populated from:
www/playwright-report/www/test-results/
backend/— Go backend binaries and serviceswww/— Vue 3 frontend using Viteintegration/— Python integration tests (API).drone.jsonnet— Drone pipelines
Schema is golang-migrate, with migrations embedded into the binaries from
backend/db/migrations (//go:embed in backend/db/migrations.go). The api
applies pending migrations on startup; backend/cmd/migrate is the manual CLI
(up, version, force).
Add a migration as 0000NN_name.up.sql + 0000NN_name.down.sql, numbered from
the highest existing prefix.
www/tests/unit/— Jest unit/component testswww/e2e/— Playwright browser tests
Do not mix them:
- Jest should not discover
e2e/ - Playwright should not depend on Jest config or setup files
Playwright does not run on this Termux/Android host. Syntax checks and repo edits can be done locally, but real Playwright execution must be validated in Drone's Linux environment.