Announce files for a bug — step 1 of 3 of sending them to the project’s bucket
const url = 'https://beta-api.plune.ai/v1/bugs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/files/uploads';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"files":[{"name":"signed-in.png","contentType":"image/png","size":48213},{"name":"trace.zip","contentType":"application/zip","size":3145728}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://beta-api.plune.ai/v1/bugs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/files/uploads \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "files": [ { "name": "signed-in.png", "contentType": "image/png", "size": 48213 }, { "name": "trace.zip", "contentType": "application/zip", "size": 3145728 } ] }'The same three steps as POST /v1/results/{id}/files/uploads (ADR 0041), for a file attached to a bug (#1066); the object goes under <prefix>/<project>/bugs/<bug>/. A project without a bucket is told which files go to /v1/bugs/{id}/files?name= instead (direct) and which have nowhere to go (skipped). The ceilings in the bucket: image 10 MiB, text 5 MiB, video 100 MiB, trace 100 MiB, other 50 MiB; 30 files, the database and the bucket together. A file in the bucket costs the budget nothing. A reader cannot announce files; a bug of another project, or in the Bin, is a 404. 600 requests a minute a person.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Header Parameters
Section titled “Header Parameters ”Which of your projects to act in — an id from GET /v1/projects. Absent, your default project. A project you are not a member of answers 404, the same as one that does not exist. Ignored under a bearer token, which is bound to the project it was minted in.
Request Body required
Section titled “Request Body required ”The files a client is about to send to a result, as it names them. Only these three fields are read.
object
object
What the file is called; only the last segment of a path is kept, cleaned of credentials. At most 200 characters once cleaned.
The media type the file will be sent with: type/subtype, optionally ; name=value parameters, no comma. The link is signed for exactly this.
The exact number of bytes of the body. The link is signed for exactly this, and complete checks it in the bucket.
Example
{ "files": [ { "name": "signed-in.png", "contentType": "image/png", "size": 48213 }, { "name": "trace.zip", "contentType": "application/zip", "size": 3145728 } ]}Responses
Section titled “ Responses ”One entry per file, in the order asked
object
One entry for each requested file, in the order they were requested.
The project has a bucket: this file goes there. PUT the bytes to url with headers, then POST /v1/files/{id}/complete.
object
The id of the file: what complete takes, and what the file is called in every list from then on.
The name as it was cleaned and will be shown.
A signed address in the customer’s bucket. It is a right, not a name: whoever holds it can write that one object until it expires. Do not print it or log it.
Exactly the headers to send, lower-case names: content-type, and content-length — the length of the body, which an HTTP client that sets it from the body itself sends already. Nothing else is signed; add no Authorization.
object
The link works for 15 minutes from the answer.
The project has no bucket and this is a picture (at most 2 MiB) or a text (at most 512 KiB): send it to POST /v1/results/{id}/files?name= as before. Nothing was reserved. A bigger one is skipped.
object
The project has no bucket and this is a trace, a video or another file: nowhere to put it. Not an error — send nothing, and keep the name with the link to the CI run as before.
object
Examples
The project has no bucket
{ "files": [ { "name": "signed-in.png", "direct": true }, { "name": "trace.zip", "skipped": "no_storage" } ]}A body that is not { files: [{ name, contentType, size }] }
object
Example generated
{ "error": "example"}No / invalid token or session
A reader of the project
object
Example generated
{ "error": "example"}No such bug in this project
object
Example generated
{ "error": "example"}It would hold more than 30 files (code: too_many_files)
object
Example generated
{ "error": "example"}A file over the ceiling of its kind in the bucket (code: file_too_large)
object
Example generated
{ "error": "example"}Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over
The project has a bucket and the server cannot open its key (code: platform_not_configured)
object
Example generated
{ "error": "example"}