Uploading XML test results
I am having difficulty doing what should be a simple POST of some test results to appveyor. The build happens on appveyor, and the tests run on a special set of hardware outside of Appveyor. I want to POST the results back to appveyor.
I am following the instructions here:
https://www.appveyor.com/docs/running-tests/#pushing-real-time-test-results-to-build-console
I have tried 3 approaches:
1) curl
2) POST with node's deprecreated `request` module
3) POST with node-fetch (which is a whatwg-fetch implementation)
In each case I am unable to see the test results in appveyor. And the second two cases yield different status codes for their responses. (404 and 415 respectively).
I am using "Content-Type: multipart/form-data" and wondering if the appveyor server that handles the form-data correctly?
Also note that for the 3rd approach (node-fetch), I have tried 3 implementations for nodejs and get the same results (form-data, formdata-polyfill and formdata-node). I tried a few implementations because I have read some server/clients have differences on how they interpret/implement the form-data spec.
Are there known issues POSTing from different clients?
Below are some simplified examples of the code I have tried that fails.
```bash
$ curl --verbose -F 'file={FILEPATH}' -H "Authorization: Bearer {TOKEN}" "https://ci.appveyor.com/api/testresults/junit/{JOBID}"
#No errors with curl... but if I look in appveyor, I see "The build job has not produced any test results."
```
```typescript
import request from 'request';
import { createReadStream } from 'graceful-fs';
import fetch from 'node-fetch'; //Using version 2.6.2 because it is CommonJS, whereas 3.x is ES module
import FormData from 'form-data';
import * as path from 'path';
//Example with `request` module (which is deprecated)
const appveyorUploadWithRequest = async (filePath: string, jobId: string, token: string) => {
const url = `https://ci.appveyor.com/api/testresults/junit/${jobId}`;
const headers = {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data'
};
await new Promise((resolve, reject) => {
request.post(
{
url,
headers,
formData: {
file: createReadStream(filePath)
}
},
(error, response, body) => {
if (error != null) {
reject(error);
return;
}
const bodyAsString = body.toString();
if (response.statusCode >= 200 && response.statusCode < 300) {
resolve(bodyAsString);
} else {
debugger;
reject(new Error(`POST ${url}, file: ${filePath}, failed: status ${response.statusCode}: ${bodyAsString}`));
}
}
);
});
};
//Example with node-fetch
const appveyorUploadWithFetch = async (filePath: string, jobId: string, token: string) => {
const url = `https://ci.appveyor.com/api/testresults/junit/${jobId}`;
const formdata = new FormData();
formdata.append('file', createReadStream(filePath), path.basename(filePath));
const headers: HeadersInit = {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data'
//Also tried adding `...formdata.getHeaders()` which includes boundary
};
const response = await fetch(url, {
method: 'POST',
body: formdata as any,
headers: headers
});
if (response.ok) {
return response.json();
} else {
debugger;
throw new Error(`POST ${url}, file: ${filePath}, failed: status ${response.status}: ${response.statusText}`);
}
};
(async () => {
await appveyorUploadWithRequest('/tmp/result.xml', 'JOBID', 'TOKEN');
//Throws 404: Job not found or access denied
})();
(async () => {
await appveyorUploadWithFetch('/tmp/result.xml', 'JOBID', 'TOKEN');
//Throws status 415.
})();
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
Support Staff 1 Posted by Feodor Fitsner on 27 Sep, 2021 05:42 PM
Sorry for the hassle! You are probably uploading XML results to a finished build? Currently, test results can be uploaded to a runnning build job only.
2 Posted by dparker on 27 Sep, 2021 06:26 PM
Yes - that's what we're doing. It is a finished build. If you do support uploading test results to a job that is finished running, please let me know.
Our workflow is roughly:
* Build on appveyor
* Run tests on our special hardware. (It polls appveyor for new builds)
* When the tests finish on our special hardware, we want to upload the test results
I think others building for IoT hardware will want to run their tests on physical hardware like us too. So being able to upload results for tests that can't run in appveyor is useful.
As a workaround we are capturing our test results in another tool. But we'd like to be able to do so on appveyor one day too.