Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload newman runs to Postman #2849

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from

Conversation

UmedJadhav
Copy link

@UmedJadhav UmedJadhav commented Sep 27, 2021

Adding the ability to upload newman run results to Postman .

Things done

  • Added a utility to upload newman runs using async-retry
  • Introduce 4 new CLI parameters
    - --publish-workspace <workspace-id>
    - --publish-workspace-skip-response
    - --publish-retry
    - --publish-upload-timeout
  • Add tests for upload run functionality
  • Add code for Run Object Serialiser

To-Do List

  • Add tests for Run Object Serialiser
  • Add tests for ingesting the new introduced CLI parameters

Refer to the following image for data flow

Newman Upload Data Flow

@codecov
Copy link

codecov bot commented Sep 27, 2021

Codecov Report

Merging #2849 (7a1b370) into develop (18e0b53) will decrease coverage by 77.96%.
The diff coverage is 7.37%.

Impacted file tree graph

@@             Coverage Diff              @@
##           develop    #2849       +/-   ##
============================================
- Coverage    90.96%   13.00%   -77.97%     
============================================
  Files           21       22        +1     
  Lines         1151     1269      +118     
  Branches       349      383       +34     
============================================
- Hits          1047      165      -882     
- Misses         104     1104     +1000     
Flag Coverage Δ
cli 13.00% <7.37%> (-69.11%) ⬇️
integration 11.89% <7.37%> (-29.11%) ⬇️
library 11.89% <7.37%> (-46.66%) ⬇️
unit 11.89% <7.37%> (-63.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
bin/newman.js 14.28% <0.00%> (-75.52%) ⬇️
lib/util.js 19.41% <0.00%> (-75.83%) ⬇️
lib/run/upload-run.js 8.04% <8.04%> (ø)
lib/run/index.js 9.28% <14.28%> (-84.47%) ⬇️
bin/util.js 0.00% <0.00%> (-100.00%) ⬇️
lib/reporters/json/index.js 0.00% <0.00%> (-100.00%) ⬇️
lib/reporters/junit/index.js 0.00% <0.00%> (-94.05%) ⬇️
lib/reporters/emojitrain.js 0.00% <0.00%> (-93.34%) ⬇️
lib/reporters/progress.js 0.00% <0.00%> (-92.86%) ⬇️
lib/run/summary.js 6.12% <0.00%> (-91.84%) ⬇️
... and 12 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 18e0b53...7a1b370. Read the comment docs.

bin/newman.js Outdated
@@ -61,9 +61,12 @@ program
.option('--cookie-jar <path>', 'Specify the path to a custom cookie jar (serialized tough-cookie JSON) ')
.option('--export-cookie-jar <path>', 'Exports the cookie jar to a file after completing the run')
.option('--verbose', 'Show detailed information of collection run and each request sent')
.option('-p, --publish-workspace <workspace-id>', 'Publishes to given workspace')
.option('--publish-workspace-skip-response', 'Skip responses (headers, body, etc) while uploading newman run to Postman')
.option('--publish-retry', 'Number of times newman can try to publish before safely erroring out.')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--publish-retries would make more sense, I think. Thoughts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense

bin/newman.js Outdated
@@ -61,9 +61,12 @@ program
.option('--cookie-jar <path>', 'Specify the path to a custom cookie jar (serialized tough-cookie JSON) ')
.option('--export-cookie-jar <path>', 'Exports the cookie jar to a file after completing the run')
.option('--verbose', 'Show detailed information of collection run and each request sent')
.option('-p, --publish-workspace <workspace-id>', 'Publishes to given workspace')
.option('--publish-workspace-skip-response', 'Skip responses (headers, body, etc) while uploading newman run to Postman')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "workspace" mean in this option? Could it simply be --publish-skip-response?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed all the CLI parameter names

bin/newman.js Outdated
@@ -61,9 +61,12 @@ program
.option('--cookie-jar <path>', 'Specify the path to a custom cookie jar (serialized tough-cookie JSON) ')
.option('--export-cookie-jar <path>', 'Exports the cookie jar to a file after completing the run')
.option('--verbose', 'Show detailed information of collection run and each request sent')
.option('-p, --publish-workspace <workspace-id>', 'Publishes to given workspace')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it simply be --publish? From the perspective of user, I feel if we have a option like --publish-workspace, we would have another option --publish which enables publishing. But this option itself is doing that, no?

Also, publish-workspace feels a little like we're publishing a workspace. 😅

Thoughts?

cc @codenirvana

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, let's keep it --publish

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and --publish-skip-response

bin/newman.js Outdated
.option('-p, --publish-workspace <workspace-id>', 'Publishes to given workspace')
.option('--publish-workspace-skip-response', 'Skip responses (headers, body, etc) while uploading newman run to Postman')
.option('--publish-retry', 'Number of times newman can try to publish before safely erroring out.')
.option('--publish-upload-timeout', 'Timeout for uploading newman runs to postman', util.cast.integer, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could simply be --publish-timeout, I think.

bin/newman.js Outdated
const runError = err || summary.run.error || summary.run.failures.length;

if (err) {
console.error(`error: ${err.message || err}\n`);
err.friendly && console.error(` ${err.friendly}\n`);
}
runError && !_.get(options, 'suppressExitCode') && process.exit(1);

runError && !newmanStatus.resultUploaded && !_.get(options, 'suppressExitCode') && process.exit(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems incorrect. If the runError is true and resultUploaded is also true, it would not exit the process with status 1, which it should given that the run has errored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an ||.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
runError && !newmanStatus.resultUploaded && !_.get(options, 'suppressExitCode') && process.exit(1);
(runError || !newmanStatus.resultUploaded) && !_.get(options, 'suppressExitCode') && process.exit(1);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this

* @returns {Promise}
*/
_uploadWithRetry = (upload, retryOptions) => {
return retry( upload,{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird spacing.

Suggested change
return retry( upload,{
return retry(upload, {

*/
start = async () => {
if(!this.uploadConfig.publishWorkspace){
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this check be made before calling the start method itself? 🤔

Also, since this is an async function. It would be better to reject the returned promise by throw-ing here (and everywhere you want to return false) with appropriate error message.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the check to run/index.js

Visit ${response.message} to view the results in postman web`);
return true;

} catch(error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let the caller catch the error and show appropriate message.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked the flow


const uploadOptions = {
url: UPLOAD_RUN_API_URL,
body: JSON.stringify(run),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON.stringify will throw in some cases. Verify that those cases won't ever occur or catch the error to handle those cases.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a try catch block

body: JSON.stringify(run),
headers: {
'Content-Type': 'application/json',
'X-API-Header': uploadConfig.postmanApiKey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the correct key for key header? Shouldn't it be X-Api-Key? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


// TODO: Add analytics call here

if (err) { // TODO -> understand when this is raised
Copy link
Member

@coditva coditva Oct 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@UmedJadhav This error is raised from the postman-runtime library if the collection run did not finish successfully.

*/
_upload = (uploadOptions) => {
return async (bail) => request.post(uploadOptions , (error, response, body) => {
if(error){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation looks weird here.

_upload = (uploadOptions) => {
return async (bail) => request.post(uploadOptions , (error, response, body) => {
if(error){
if(error.code === 'ECONNREFUSED') { // Retry only if the ERROR is ERRCONNECT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: 'ECONNREFUSED' should be a const.

return async (bail) => request.post(uploadOptions , (error, response, body) => {
if(error){
if(error.code === 'ECONNREFUSED') { // Retry only if the ERROR is ERRCONNECT
throw new Error(error.message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the error message is same, why not just throw the error itself?

Suggested change
throw new Error(error.message);
throw error;

return bail(error); // For other errors , dont retry
}

// Handle exact status codes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't seem to be handling the exact status codes. 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use a switch-case in this case (pun intended.)

* @param {Object} uploadOptions
* @returns {function} Returns an async function which can be used by async-retry library to have retries
*/
_upload = (uploadOptions) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to return a function, it should be called something like _getUploadRetryable.
Or, don't return a function! Just bind the params where you're using it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants