diff --git a/README.md b/README.md index fbda6608..74e12725 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,57 @@ # accelq-ci-github-actions + Github Actions ACCELQ CI Plugin + +## Inputs + +### `appURL` +**Required** +Your ACCELQ application URL in the format: https://hostname:port + +### `userName` +**Required** +Your ACCELQ User ID + +### `apiKey` +**Required** +API key available in the Profile section of ACCELQ + +### `tenantCode` +**Required** +Tenant Code displayed in the Profile section of ACCELQ + +### `jobId` +**Required** +This ID should come from the job saved in ACCELQ + +### `runParam` +Run parameters in JSON string format. Example: +``` +{ + "username": "John Todd", + "password": "bxW&=UVw" +} +``` + +### `proxyHost` +Proxy Host + +### `proxyPort` +Proxy Port + +### `stepFailureThreshold` +Percentage of ACCELQ test case failure, beyond which this step will be marked as a failure in the CI pipeline. +If this is zero, even a single failed test will cause the step to fail. If you never want to fail this step due to failing automation tests, input -1. +Allowed values: integer between 0 and 100 or. Default is -1. + +### `maxWaitTimeInMins` +Maximum time to wait for the job to be picked up by an ACCELQ Agent. Default is 15 mins. + +### `waitForJobCompletion` +If true, wait for the job to be completed. If false, run the job and exit. Default is true. + + +## Outputs + +### `result-url` +The ACCELQ url to access the job results \ No newline at end of file diff --git a/action.yml b/action.yml index 631c359d..f448db72 100644 --- a/action.yml +++ b/action.yml @@ -32,7 +32,12 @@ inputs: maxWaitTimeInMins: description: "Maximum time to wait for the job to be picked up by an ACCELQ Agent. Default is 15 mins." required: false - + waitForJobCompletion: + description: 'If true, wait for the job to be completed. If false, run the job and exit. Default is true.' + required: false +outputs: + result-url: + description: "The ACCELQ url to access the job results" runs: using: 'node12' main: 'index.js' diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..64d492b3 --- /dev/null +++ b/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +export NODE_OPTIONS=--openssl-legacy-provider +npm run build diff --git a/index.js b/index.js index 32d41a28..558f593f 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -(()=>{"use strict";var e={955:(e,t)=>{var n,o;Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.PASS="pass",e.FAIL="fail",e.NOT_RUN="notRun",e.RUNNING="running",e.INFO="info",e.FATAL="fatal",e.WARN="warn",e.ALL="all"}(n||(n={})),function(e){e.NOT_APPLICABLE="Not Applicable",e.SCHEDULED="Scheduled",e.IN_PROGRESS="In Progress",e.COMPLETED="Completed",e.ABORTED="Aborted",e.FAILED="Failed To Start",e.RECURRING="Recurring",e.ERROR="Error",e.CONTINUOUS_INTEGRATION="Continuous Integration"}(o||(o={}));const r={LOG_DELIMITER:">>> ",USER_AGENT:"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",JOB_PICKUP_RETRY_TIME_THRESHOLD_IN_MINS:15,JOB_STATUS_POLL_TIME:3e4,JOB_WEB_LINK:"#/forward?entityType=9&resultId={0}",EXT_JOB_WEB_LINK:"#/resultext?tenant={0}&resultId={1}",API_VERSION:"1.0",AQ_RESULT_INFO_KEY:"AQReportInfo",TEST_CASE_STATUS:n,TEST_JOB_STATUS:o};t.default=r},807:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0});const n={validateJobID:e=>{try{if(+e<=0)return"Must be a number greater than 0"}catch(t){return"Not a number"}return null},validateTenantCode:function(e){return this.validateGenericField(e)},validateAppURL:e=>{try{new URL(e)}catch(t){return"Not a URL"}return null},validateGenericField:e=>{try{if(null==e||0==e.length)return"Cannot be empty"}catch(t){return"Cannot be empty"}return null},validateProjectCode:function(e){return this.validateGenericField(e)},validateAPIKey:function(e){return this.validateGenericField(e)},validateUserId:e=>{try{const t=new RegExp(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);if(null==e||0==e.length)return"Cannot be empty";if(!t.test(e))return"User ID must be in email format"}catch(t){}return null}};t.default=n},584:function(e,t,n){var o=this&&this.__awaiter||function(e,t,n,o){return new(n||(n=Promise))((function(r,a){function s(e){try{l(o.next(e))}catch(t){a(t)}}function i(e){try{l(o.throw(e))}catch(t){a(t)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,i)}l((o=o.apply(e,t||[])).next())}))},r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=r(n(955)),s=r(n(949)),i=r(n(376)),l=n(906),u={BASE_URL:"",API_ENDPOINT:"",PROXY_HOST:"",PROXY_PORT:80,setProxy:function(e,t){this.PROXY_HOST=e,this.PROXY_PORT=0==t?80:t},isProxySet:function(){return this.PROXY_HOST&&this.PROXY_HOST.length>0},getProxyConfig:function(){let e=this.BASE_URL.split("://")[0];return new s.default(`${e}://${this.PROXY_HOST}:${this.PROXY_PORT}`)},testConnection:function(e,t,n,r,s){return o(this,void 0,void 0,(function*(){const o=l.AQUtil.getRunParam(n,r,s);try{let r;this.isProxySet()&&(r=this.getProxyConfig());const s=yield i.default.request({method:"POST",url:`${this.API_ENDPOINT}/jobs/${n}/validate-ci-job`,httpsAgent:r,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:e,USER_ID:t,"Content-Type":"application/json"},data:JSON.stringify(o)});return 200==s.status||s.status,""}catch(u){const e=u.response;return e&&404!=e.status?401==e.status?"Connection request failed. Please check connection parameters.":e.status>=500?"Server Error: "+e.data.message:200!=e.status?"Template Job ID does not exist.":null:"Connection request failed. Please check the URL and Tenant Code."}}))},triggerJob:function(e,t,n,r,s,u){return o(this,void 0,void 0,(function*(){const o=l.AQUtil.getRunParam(n,r,s,u);try{let r;this.isProxySet()&&(r=this.getProxyConfig());const s=yield i.default.request({method:"PUT",url:`${this.API_ENDPOINT}/jobs/${n}/trigger-ci-job`,httpsAgent:r,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:e,USER_ID:t,"Content-Type":"application/json"},data:JSON.stringify(o)}),l=s.data;return 200==s.status||204==s.status?{pid:l[0]}:l}catch(d){return console.log("Error is: "+d.response.data.message),null}}))},setBaseURL:function(e,t){this.BASE_URL="/"==e.charAt(e.length-1)?e:e+"/",this.API_ENDPOINT=this.BASE_URL+"awb/api/"+a.default.API_VERSION+"/"+t},getResultExternalAccessURL:function(e,t){let n=a.default.EXT_JOB_WEB_LINK;return n=n.replace("{0}",t),n=n.replace("{1}",e),this.BASE_URL+n},getJobSummary:function(e,t,n){return o(this,void 0,void 0,(function*(){let o;this.isProxySet()&&(o=this.getProxyConfig());return(yield i.default.request({method:"GET",httpsAgent:o,url:`${this.API_ENDPOINT}/runs/${e}`,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:t,USER_ID:n,"Content-Type":"application/json"}})).data}))}};t.default=u},906:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AQUtil=void 0,t.AQUtil={getRunParam:(e,t,n,o)=>{let r={};return t&&t.length>0&&(r.runProperties=JSON.parse(t)),r.jobPid=+e,o&&(r.agentNameList=o),Number.isFinite(n)&&(r.expireTimeInMinutes=n),r},getRunParamJsonPayload:e=>{if(null!=e&&0!=e.trim().length)try{return JSON.parse(e),e}catch(t){const n=e.split("&");let o={};return n.forEach((e=>{const t=e.split("=");if(2==t.length){const e=t[0].trim(),n=t[1].trim();""!==e&&""!==n&&(o[e]=n)}})),JSON.stringify(o)}},getFormattedTime:(e,t)=>{const n=new Date(e),o=new Date(t).getTime()-n.getTime(),r=+(o/1e3%60).toFixed(),a=+(o/6e4%60).toFixed(),s=+(o/36e5%24).toFixed(),i=+(o/864e5%365).toFixed();let l="";return 0!=i&&(l+=i>1?i+" days":i+" day"),0!=s&&(l+=s>1?s+" hrs":s+" hr"),0!=a&&(l+=" "+(a>1?a+" mins":a+" min")),0!=r&&(l+=" "+(r>1?r+" seconds":r+" second")),l},isWaitTimeExceeded:(e,t)=>Math.floor((Date.now()-e)/6e4)>t}},492:function(e,t,n){var o=this&&this.__awaiter||function(e,t,n,o){return new(n||(n=Promise))((function(r,a){function s(e){try{l(o.next(e))}catch(t){a(t)}}function i(e){try{l(o.throw(e))}catch(t){a(t)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,i)}l((o=o.apply(e,t||[])).next())}))},r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=r(n(955)),s=r(n(807)),i=r(n(584)),l=n(906),u=n(953);function d(e){return new Promise((t=>setTimeout(t,e)))}function c(e){return e>=-1&&e<=100}function f(e){return e&&Number.isInteger(+e)?+e:a.default.JOB_PICKUP_RETRY_TIME_THRESHOLD_IN_MINS}!function(){var e;o(this,void 0,void 0,(function*(){try{const t=u.getInput("appURL",{required:!0})||"",n=u.getInput("userName",{required:!0})||"",r=u.getInput("apiKey",{required:!0})||"",T=u.getInput("tenantCode",{required:!0})||"",p=u.getInput("jobId",{required:!0})||"",h=u.getInput("runParam")||"",g=u.getInput("proxyHost")||"",E=u.getInput("proxyPort")||"",_=u.getInput("stepFailureThreshold")||"",S=u.getInput("maxWaitTimeInMins")||"";let I;if(I=s.default.validateAppURL(t),null!=I)throw new Error("ACCELQ App URL: "+I);if(I=s.default.validateUserId(n),null!=I)throw new Error("ACCELQ User ID: "+I);if(I=s.default.validateAPIKey(r),null!=I)throw new Error("API Key: "+I);if(I=s.default.validateTenantCode(T),null!=I)throw new Error("Tenant Code: "+I);if(I=s.default.validateJobID(p),null!=I)throw new Error("ACCELQ CI Job ID: "+I);if(I=yield function(e,t,n,r,a,s,u,d,c){return o(this,void 0,void 0,(function*(){i.default.setBaseURL(e,r),u&&u.length>0?i.default.setProxy(u,+d):i.default.setProxy("",0);const o=l.AQUtil.getRunParamJsonPayload(s);return yield i.default.testConnection(n,t,a,o,f(c))}))}(t,n,r,T,p,h,g,E,S),null===I)throw new Error("Something went wrong in extension");if(I)throw new Error(I);I=yield function(e,t,n,r,s,u,T,p,h,g){return o(this,void 0,void 0,(function*(){let o=null,E=0,_=+h;try{i.default.setBaseURL(e,r),T&&T.length>0?i.default.setProxy(T,+p):i.default.setProxy("",0),console.log("******************************************"),console.log("*** Begin: ACCELQ Test Automation Step ***"),console.log("******************************************"),console.log();const m=l.AQUtil.getRunParamJsonPayload(u),A=f(g),R=yield i.default.triggerJob(n,t,s,m,A);if(null==R)throw new Error("Unable to submit the Job, check plugin log stack");if(null!=R.cause)throw new Error(R.cause);E=R.pid;let P=0,O=0,U=0,y=0,C="",N=0;const v=Date.now(),L=i.default.getResultExternalAccessURL(E.toString(),r);let w=!1,b=!1;for(;;){try{o=yield i.default.getJobSummary(E,n,t),w=!1}catch(I){w=!0,console.warn("Warn: Issue fetching Job Summary: ",I.message)}if(!w){if(null!=o.cause)throw new Error(o.cause);if(null!=o.summary&&(o=o.summary),P=+o.pass,O=+o.fail,y=+o.notRun,0==N){N=1;const e=o.purpose,t=o.scnName,n=o.testSuiteName,r=o.testcaseCount;null!=n&&n.length>0?console.log("Test Suite Name: "+n):console.log("Scenario Name: "+t),console.log("Purpose: "+e),console.log("Total Test Cases: "+r),console.log("Step Failure threshold: "+h),console.log("Max Wait Time in Minutes: "+A),console.log(),"number"!==typeof(S=_)||Number.isNaN(S)||Number.isInteger(S)||(_=Math.trunc(_),console.log(`Warning: Invalid value (${_}) passed for Step Failure Threshold. Truncating the value to ${_} (Only integers between 0 and 100, and -1 are allowed).`)),c(_)||(console.log(`Warning: Ignoring the Step Failure threshold. Invalid value (${_}) passed. Valid values are 0 to 100, or -1 to ignore threshold.`),_=0)}if(C=o.status.toUpperCase(),C===a.default.TEST_JOB_STATUS.SCHEDULED.toUpperCase()||b||(b=!0,console.log("Results Link: "+L),console.log("Need to abort? Click on the link above, login to ACCELQ and abort the run."),console.log()),C==a.default.TEST_JOB_STATUS.COMPLETED.toUpperCase()){const e=" "+l.AQUtil.getFormattedTime(o.startTimestamp,o.completedTimestamp);console.log("Status: "+o.status.toUpperCase()+" ("+e.trim()+")")}else console.log("Status: "+o.status.toUpperCase());if(b&&(U=P+O+y,console.log("Total "+U+": "+P+" Pass / "+O+" Fail"),console.log()),C==a.default.TEST_JOB_STATUS.SCHEDULED.toUpperCase()&&l.AQUtil.isWaitTimeExceeded(v,A))throw new Error(a.default.LOG_DELIMITER+"No agent available to pickup the job");if(C==a.default.TEST_JOB_STATUS.COMPLETED.toUpperCase()||C==a.default.TEST_JOB_STATUS.ABORTED.toUpperCase()||C==a.default.TEST_JOB_STATUS.FAILED.toUpperCase()||C==a.default.TEST_JOB_STATUS.ERROR.toUpperCase())break}yield d(a.default.JOB_STATUS_POLL_TIME)}console.log("Results Link: "+L),console.log();const x=Math.trunc(O/U*100);if(C==a.default.TEST_JOB_STATUS.ABORTED.toUpperCase()||C==a.default.TEST_JOB_STATUS.FAILED.toUpperCase()||C==a.default.TEST_JOB_STATUS.ERROR.toUpperCase())throw new Error(a.default.LOG_DELIMITER+"Run Failed");if(O>0&&-1!=_&&x>=_)throw new Error(a.default.LOG_DELIMITER+"Automation test step failed (test case failure count exceeds the threshold limit)");return{jobId:E,status:!0,error:null}}catch(I){if(o=yield i.default.getJobSummary(E,n,t),null!=o.cause)throw new Error(o.cause);return null!=o.summary&&(o=o.summary),console.log("Status: "+o.status),console.log("Pass: "+o.pass),{jobId:E,status:!1,error:I}}var S}))}(t,n,r,T,p,h,g,E,_,S),I.status?console.log("Run Completed!!!"):u.setFailed((null===(e=I.error)||void 0===e?void 0:e.message)||"Job Failed!!!")}catch(t){u.setFailed(t.message)}finally{console.log("**********************************************"),console.log("*** Completed: ACCELQ Test Automation Step ***"),console.log("**********************************************")}}))}()},953:e=>{e.exports=require("@actions/core")},376:e=>{e.exports=require("axios")},949:e=>{e.exports=require("https-proxy-agent")}},t={};(function n(o){var r=t[o];if(void 0!==r)return r.exports;var a=t[o]={exports:{}};return e[o].call(a.exports,a,a.exports,n),a.exports})(492)})(); \ No newline at end of file +(()=>{"use strict";var e={955:(e,t)=>{var n,o;Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.PASS="pass",e.FAIL="fail",e.NOT_RUN="notRun",e.RUNNING="running",e.INFO="info",e.FATAL="fatal",e.WARN="warn",e.ALL="all"}(n||(n={})),function(e){e.NOT_APPLICABLE="Not Applicable",e.SCHEDULED="Scheduled",e.IN_PROGRESS="In Progress",e.COMPLETED="Completed",e.ABORTED="Aborted",e.FAILED="Failed To Start",e.RECURRING="Recurring",e.ERROR="Error",e.CONTINUOUS_INTEGRATION="Continuous Integration"}(o||(o={}));const r={LOG_DELIMITER:">>> ",USER_AGENT:"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",JOB_PICKUP_RETRY_TIME_THRESHOLD_IN_MINS:15,JOB_STATUS_POLL_TIME:3e4,JOB_WEB_LINK:"#/forward?entityType=9&resultId={0}",EXT_JOB_WEB_LINK:"#/resultext?tenant={0}&resultId={1}",API_VERSION:"1.0",AQ_RESULT_INFO_KEY:"AQReportInfo",TEST_CASE_STATUS:n,TEST_JOB_STATUS:o};t.default=r},807:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0});const n={validateJobID:e=>{try{if(+e<=0)return"Must be a number greater than 0"}catch(t){return"Not a number"}return null},validateTenantCode:function(e){return this.validateGenericField(e)},validateAppURL:e=>{try{new URL(e)}catch(t){return"Not a URL"}return null},validateGenericField:e=>{try{if(null==e||0==e.length)return"Cannot be empty"}catch(t){return"Cannot be empty"}return null},validateProjectCode:function(e){return this.validateGenericField(e)},validateAPIKey:function(e){return this.validateGenericField(e)},validateUserId:e=>{try{const t=new RegExp(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);if(null==e||0==e.length)return"Cannot be empty";if(!t.test(e))return"User ID must be in email format"}catch(t){}return null}};t.default=n},584:function(e,t,n){var o=this&&this.__awaiter||function(e,t,n,o){return new(n||(n=Promise))((function(r,a){function s(e){try{i(o.next(e))}catch(t){a(t)}}function l(e){try{i(o.throw(e))}catch(t){a(t)}}function i(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,l)}i((o=o.apply(e,t||[])).next())}))},r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=r(n(955)),s=r(n(949)),l=r(n(376)),i=n(906),u={BASE_URL:"",API_ENDPOINT:"",PROXY_HOST:"",PROXY_PORT:80,setProxy:function(e,t){this.PROXY_HOST=e,this.PROXY_PORT=0==t?80:t},isProxySet:function(){return this.PROXY_HOST&&this.PROXY_HOST.length>0},getProxyConfig:function(){let e=this.BASE_URL.split("://")[0];return new s.default(`${e}://${this.PROXY_HOST}:${this.PROXY_PORT}`)},testConnection:function(e,t,n,r,s){return o(this,void 0,void 0,(function*(){const o=i.AQUtil.getRunParam(n,r,s);try{let r;this.isProxySet()&&(r=this.getProxyConfig());const s=yield l.default.request({method:"POST",url:`${this.API_ENDPOINT}/jobs/${n}/validate-ci-job`,httpsAgent:r,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:e,USER_ID:t,"Content-Type":"application/json"},data:JSON.stringify(o)});return 200==s.status||s.status,""}catch(u){const e=u.response;return e&&404!=e.status?401==e.status?"Connection request failed. Please check connection parameters.":e.status>=500?"Server Error: "+e.data.message:200!=e.status?"Template Job ID does not exist.":null:"Connection request failed. Please check the URL and Tenant Code."}}))},triggerJob:function(e,t,n,r,s,u){return o(this,void 0,void 0,(function*(){const o=i.AQUtil.getRunParam(n,r,s,u);try{let r;this.isProxySet()&&(r=this.getProxyConfig());const s=yield l.default.request({method:"PUT",url:`${this.API_ENDPOINT}/jobs/${n}/trigger-ci-job`,httpsAgent:r,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:e,USER_ID:t,"Content-Type":"application/json"},data:JSON.stringify(o)}),i=s.data;return 200==s.status||204==s.status?{pid:i[0]}:i}catch(c){return console.log("Error is: "+c.response.data.message),null}}))},setBaseURL:function(e,t){this.BASE_URL="/"==e.charAt(e.length-1)?e:e+"/",this.API_ENDPOINT=this.BASE_URL+"awb/api/"+a.default.API_VERSION+"/"+t},getResultExternalAccessURL:function(e,t){let n=a.default.EXT_JOB_WEB_LINK;return n=n.replace("{0}",t),n=n.replace("{1}",e),this.BASE_URL+n},getJobSummary:function(e,t,n){return o(this,void 0,void 0,(function*(){let o;this.isProxySet()&&(o=this.getProxyConfig());return(yield l.default.request({method:"GET",httpsAgent:o,url:`${this.API_ENDPOINT}/runs/${e}`,headers:{"User-Agent":a.default.USER_AGENT,API_KEY:t,USER_ID:n,"Content-Type":"application/json"}})).data}))}};t.default=u},906:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AQUtil=void 0,t.AQUtil={getRunParam:(e,t,n,o)=>{let r={};return t&&t.length>0&&(r.runProperties=JSON.parse(t)),r.jobPid=+e,o&&(r.agentNameList=o),Number.isFinite(n)&&(r.expireTimeInMinutes=n),r},getRunParamJsonPayload:e=>{if(null!=e&&0!=e.trim().length)try{return JSON.parse(e),e}catch(t){const n=e.split("&");let o={};return n.forEach((e=>{const t=e.split("=");if(2==t.length){const e=t[0].trim(),n=t[1].trim();""!==e&&""!==n&&(o[e]=n)}})),JSON.stringify(o)}},getFormattedTime:(e,t)=>{const n=new Date(e),o=new Date(t).getTime()-n.getTime(),r=+(o/1e3%60).toFixed(),a=+(o/6e4%60).toFixed(),s=+(o/36e5%24).toFixed(),l=+(o/864e5%365).toFixed();let i="";return 0!=l&&(i+=l>1?l+" days":l+" day"),0!=s&&(i+=s>1?s+" hrs":s+" hr"),0!=a&&(i+=" "+(a>1?a+" mins":a+" min")),0!=r&&(i+=" "+(r>1?r+" seconds":r+" second")),i},isWaitTimeExceeded:(e,t)=>Math.floor((Date.now()-e)/6e4)>t}},492:function(e,t,n){var o=this&&this.__awaiter||function(e,t,n,o){return new(n||(n=Promise))((function(r,a){function s(e){try{i(o.next(e))}catch(t){a(t)}}function l(e){try{i(o.throw(e))}catch(t){a(t)}}function i(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,l)}i((o=o.apply(e,t||[])).next())}))},r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=r(n(955)),s=r(n(807)),l=r(n(584)),i=n(906),u=n(953);function c(e){return new Promise((t=>setTimeout(t,e)))}function d(e){return e>=-1&&e<=100}function f(e){return e&&Number.isInteger(+e)?+e:a.default.JOB_PICKUP_RETRY_TIME_THRESHOLD_IN_MINS}!function(){var e;o(this,void 0,void 0,(function*(){try{const t=u.getInput("appURL",{required:!0})||"",n=u.getInput("userName",{required:!0})||"",r=u.getInput("apiKey",{required:!0})||"",p=u.getInput("tenantCode",{required:!0})||"",T=u.getInput("jobId",{required:!0})||"",h=u.getInput("runParam")||"",g=u.getInput("proxyHost")||"",E=u.getInput("proxyPort")||"",_=u.getInput("stepFailureThreshold")||"",S=u.getInput("maxWaitTimeInMins")||"",m="true"===(u.getInput("waitForJobCompletion")||"true").toLowerCase();let I;if(I=s.default.validateAppURL(t),null!=I)throw new Error("ACCELQ App URL: "+I);if(I=s.default.validateUserId(n),null!=I)throw new Error("ACCELQ User ID: "+I);if(I=s.default.validateAPIKey(r),null!=I)throw new Error("API Key: "+I);if(I=s.default.validateTenantCode(p),null!=I)throw new Error("Tenant Code: "+I);if(I=s.default.validateJobID(T),null!=I)throw new Error("ACCELQ CI Job ID: "+I);if(I=yield function(e,t,n,r,a,s,u,c,d){return o(this,void 0,void 0,(function*(){l.default.setBaseURL(e,r),u&&u.length>0?l.default.setProxy(u,+c):l.default.setProxy("",0);const o=i.AQUtil.getRunParamJsonPayload(s);return yield l.default.testConnection(n,t,a,o,f(d))}))}(t,n,r,p,T,h,g,E,S),null===I)throw new Error("Something went wrong in extension");if(I)throw new Error(I);I=yield function(e,t,n,r,s,u,p,T,h,g,E){return o(this,void 0,void 0,(function*(){let o=null,_=0,S=+h;try{l.default.setBaseURL(e,r),p&&p.length>0?l.default.setProxy(p,+T):l.default.setProxy("",0),console.log("******************************************"),console.log("*** Begin: ACCELQ Test Automation Step ***"),console.log("******************************************"),console.log();const A=i.AQUtil.getRunParamJsonPayload(u),R=f(g),P=yield l.default.triggerJob(n,t,s,A,R);if(null==P)throw new Error("Unable to submit the Job, check plugin log stack");if(null!=P.cause)throw new Error(P.cause);_=P.pid;let U=0,O=0,y=0,C=0,L="",N=0;const v=Date.now(),w=l.default.getResultExternalAccessURL(_.toString(),r);let b=!1,x=!1;for(console.log("Wait for job completion: "+E);E;){try{o=yield l.default.getJobSummary(_,n,t),b=!1}catch(I){b=!0,console.warn("Warn: Issue fetching Job Summary: ",I.message)}if(!b){if(null!=o.cause)throw new Error(o.cause);if(null!=o.summary&&(o=o.summary),U=+o.pass,O=+o.fail,C=+o.notRun,0==N){N=1;const e=o.purpose,t=o.scnName,n=o.testSuiteName,r=o.testcaseCount;null!=n&&n.length>0?console.log("Test Suite Name: "+n):console.log("Scenario Name: "+t),console.log("Purpose: "+e),console.log("Total Test Cases: "+r),console.log("Step Failure threshold: "+h),console.log("Max Wait Time in Minutes: "+R),console.log(),"number"!==typeof(m=S)||Number.isNaN(m)||Number.isInteger(m)||(S=Math.trunc(S),console.log(`Warning: Invalid value (${S}) passed for Step Failure Threshold. Truncating the value to ${S} (Only integers between 0 and 100, and -1 are allowed).`)),d(S)||(console.log(`Warning: Ignoring the Step Failure threshold. Invalid value (${S}) passed. Valid values are 0 to 100, or -1 to ignore threshold.`),S=0)}if(L=o.status.toUpperCase(),L===a.default.TEST_JOB_STATUS.SCHEDULED.toUpperCase()||x||(x=!0,console.log("Results Link: "+w),console.log("Need to abort? Click on the link above, login to ACCELQ and abort the run."),console.log()),L==a.default.TEST_JOB_STATUS.COMPLETED.toUpperCase()){const e=" "+i.AQUtil.getFormattedTime(o.startTimestamp,o.completedTimestamp);console.log("Status: "+o.status.toUpperCase()+" ("+e.trim()+")")}else console.log("Status: "+o.status.toUpperCase());if(x&&(y=U+O+C,console.log("Total "+y+": "+U+" Pass / "+O+" Fail"),console.log()),L==a.default.TEST_JOB_STATUS.SCHEDULED.toUpperCase()&&i.AQUtil.isWaitTimeExceeded(v,R))throw new Error(a.default.LOG_DELIMITER+"No agent available to pickup the job");if(L==a.default.TEST_JOB_STATUS.COMPLETED.toUpperCase()||L==a.default.TEST_JOB_STATUS.ABORTED.toUpperCase()||L==a.default.TEST_JOB_STATUS.FAILED.toUpperCase()||L==a.default.TEST_JOB_STATUS.ERROR.toUpperCase())break}yield c(a.default.JOB_STATUS_POLL_TIME)}console.log("Results Link: "+w),console.log();const D=Math.trunc(O/y*100);if(L==a.default.TEST_JOB_STATUS.ABORTED.toUpperCase()||L==a.default.TEST_JOB_STATUS.FAILED.toUpperCase()||L==a.default.TEST_JOB_STATUS.ERROR.toUpperCase())throw new Error(a.default.LOG_DELIMITER+"Run Failed");if(O>0&&-1!=S&&D>=S)throw new Error(a.default.LOG_DELIMITER+"Automation test step failed (test case failure count exceeds the threshold limit)");return{jobId:_,resultUrl:w,status:!0,error:null}}catch(I){if(o=yield l.default.getJobSummary(_,n,t),null!=o.cause)throw new Error(o.cause);return null!=o.summary&&(o=o.summary),console.log("Status: "+o.status),console.log("Pass: "+o.pass),{jobId:_,resultUrl:"",status:!1,error:I}}var m}))}(t,n,r,p,T,h,g,E,_,S,m),I.status?console.log("Run Completed!!!"):u.setFailed((null===(e=I.error)||void 0===e?void 0:e.message)||"Job Failed!!!"),u.setOutput("result-url",I.resultUrl)}catch(t){u.setFailed(t.message)}finally{console.log("**********************************************"),console.log("*** Completed: ACCELQ Test Automation Step ***"),console.log("**********************************************")}}))}()},953:e=>{e.exports=require("@actions/core")},376:e=>{e.exports=require("axios")},949:e=>{e.exports=require("https-proxy-agent")}},t={};(function n(o){var r=t[o];if(void 0!==r)return r.exports;var a=t[o]={exports:{}};return e[o].call(a.exports,a,a.exports,n),a.exports})(492)})(); \ No newline at end of file diff --git a/index.ts b/index.ts index ce055d95..e27999a4 100644 --- a/index.ts +++ b/index.ts @@ -38,7 +38,7 @@ function getMaxWaitTime(maxWaitTimeInMins: string) { } async function executeJob(appURL:string, userName:string, apiKey:string, tenantCode:string, jobId:string, - runParam:string, proxyHost:string, proxyPort:string, stepFailureThreshold: string, maxWaitTimeInMins: string) { + runParam:string, proxyHost:string, proxyPort:string, stepFailureThreshold: string, maxWaitTimeInMins: string, waitForJobCompletion: boolean) { let summaryObj = null; let realJobPid = 0; let failureThreshold = +stepFailureThreshold; @@ -71,7 +71,8 @@ async function executeJob(appURL:string, userName:string, apiKey:string, tenantC const resultAccessURL = AQRestClient.getResultExternalAccessURL(realJobPid.toString(), tenantCode); let error = false; let hasLoggedLinks = false; - while(true) { + console.log("Wait for job completion: " + waitForJobCompletion) + while(waitForJobCompletion) { try { summaryObj = await AQRestClient.getJobSummary(realJobPid, apiKey, userName); error = false; @@ -160,6 +161,7 @@ async function executeJob(appURL:string, userName:string, apiKey:string, tenantC } return { jobId: realJobPid, + resultUrl: resultAccessURL, status: true, error: null }; @@ -175,6 +177,7 @@ async function executeJob(appURL:string, userName:string, apiKey:string, tenantC console.log("Pass: " + summaryObj["pass"]); return { jobId: realJobPid, + resultUrl: "", status: false, error: e, }; @@ -193,10 +196,11 @@ async function run() { const proxyPort = core.getInput('proxyPort') || ""; const stepFailureThreshold = core.getInput('stepFailureThreshold') || ""; const maxWaitTimeInMins = core.getInput('maxWaitTimeInMins') || ""; + const waitForJobCompletion = (core.getInput('waitForJobCompletion') || "true").toLowerCase() === "true"; // validateFORM let res: string | null | { - jobId: number; status: boolean, error?: any }; + jobId: number; resultUrl: string, status: boolean, error?: any }; res = AQFormValidate.validateAppURL(appURL); if (res != null) { throw new Error('ACCELQ App URL: ' + res); @@ -227,12 +231,13 @@ async function run() { throw new Error(res); } // executeJob - res = await executeJob(appURL, userName, apiKey, tenantCode, jobId, runParam, proxyHost, proxyPort, stepFailureThreshold, maxWaitTimeInMins); + res = await executeJob(appURL, userName, apiKey, tenantCode, jobId, runParam, proxyHost, proxyPort, stepFailureThreshold, maxWaitTimeInMins, waitForJobCompletion); if (res.status) { console.log('Run Completed!!!'); } else { core.setFailed(res.error?.message || "Job Failed!!!"); } + core.setOutput("result-url", res.resultUrl); } catch (err: any) { core.setFailed(err.message); diff --git a/node_modules/.bin/webpack b/node_modules/.bin/webpack old mode 100644 new mode 100755