feat(cypress): upload failure screenshots to the v2 media endpoint#8981
feat(cypress): upload failure screenshots to the v2 media endpoint#8981xinyeji wants to merge 6 commits into
Conversation
Updates the Cypress failure-screenshot upload (from #8574) to the production v2 Test Optimization media contract: - Send the two now-required headers: - X-Dd-Idempotency-Key = `{trace_id}:{filename}` — stable per artifact and reused on retry, so a retried upload overwrites the same stored object instead of creating a duplicate (the Cypress filename encodes test + attempt). - X-Dd-Media-Captured-At = capture time in epoch ms, taken from the screenshot's `takenAt` (mtime / now fallback), stamped once and resent unchanged on retry (it is part of the stored object key). - Drop the temporary PoC bits: the `test-drive-test-failure-media-bucket` header and the `DD_POC_SITE` host override. - Agentless uploads go to the normal api.<site> host with DD-API-KEY. Agent (evp_proxy) mode upload stays disabled until the Datadog Agent allow-lists POST /api/unstable/ci/test-runs/<trace_id>/media (follow-up). Backend: DataDog/dd-source#443668. Builds on Juan's PoC #8574. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Overall package sizeSelf size: 6.27 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.1.0 | 101.28 kB | 840.46 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
|
BenchmarksBenchmark execution time: 2026-06-18 21:13:54 Comparing candidate commit cf7e1c9 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 1950 metrics, 15 unstable metrics.
|
Extends the media upload to Cypress's per-spec video:
- getContentType maps .mp4 -> video/mp4 and .webm -> video/webm.
- afterSpec uploads results.video to each failed test run's trace_id (Cypress
records one video per spec, so it is attached to every failed test in the
spec). Capture time falls back to the video file mtime (no per-test takenAt).
- New uploadTestVideo() reuses the same media request + idempotency key
(`{trace_id}:{filename}`), so an upload retry overwrites instead of duplicating.
Backend + UI already support video (mp4/webm); this closes the tracer side for
Cypress. Image (screenshot) and video now both flow end-to-end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The debug line concatenated url.toString() (trailing '/') with the leading-slash path, logging https://api.<site>//api/unstable/... The actual request was always correct (request helper uses url.hostname + options.path separately); this just makes the log resolve to a single, clean URL. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What does this PR do?
Brings the Cypress failure-screenshot upload (innovation-day PoC #8574, authored by @juan-fernandez) up to the production v2 Test Optimization media contract so it works against the real bucket-backed backend (DataDog/dd-source#443668).
The first 3 commits are #8574 cherry-picked onto
master(Juan's authorship preserved); the last commit is the v2 update. Picking up the library work scoped to @sebas in the innovation-week thread.Changes (v2 delta)
packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js):X-Dd-Idempotency-Key={trace_id}:{filename}— stable per artifact, reused on retry, so a retried upload overwrites the same stored object instead of duplicating (the Cypress filename encodes test + attempt).X-Dd-Media-Captured-At= capture time in epoch ms, from the screenshot'stakenAt(mtime / now fallback), stamped once and resent unchanged on retry (it's part of the stored object key).test-drive-test-failure-media-bucketheader and theDD_POC_SITEhost override (+ its config entry).api.<site>host withDD-API-KEY(the exporter's existing_apiUrl).cypress-plugin.js) computes the key + capture time per screenshot and threads them through the exporter.Motivation
Cypress already captures screenshots for failed runs. The v2 backend requires a stable idempotency key + a real capture timestamp from the tracer; without them the upload is rejected (
400 MALFORMED). This wires those in and removes the PoC-only host/header so it targets the real endpoint.Additional notes / follow-ups
canUploadTestScreenshots()is false in agent mode): the Datadog Agent'sevp_proxymust allow-listPOST /api/unstable/ci/test-runs/<trace_id>/mediabefore screenshots can be forwarded through it. Agentless works today. Tracking as a follow-up.master(the spec diverged heavily); a mock-intake header-assertion test is a follow-up.test-run-media-e2e-test-plan.md(build the tracer from this branch → run a failing Cypress test → assert the 201 + both headers → backend GET → web-ui Media tab). Frontend: DataDog/web-ui#320875.🤖 Generated with Claude Code