@currents/cmd 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -1
- package/dist/bin/index.js +49 -41
- package/dist/index.js +9 -8
- package/dist/skills/currents-cli/SKILL.md +22 -104
- package/{dist/skills/currents-cli/references → docs}/ci-setup.md +12 -1
- package/{dist/skills/currents-cli/references → docs}/sessions.md +4 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
"use strict";var Or=Object.create;var K=Object.defineProperty;var Sr=Object.getOwnPropertyDescriptor;var yr=Object.getOwnPropertyNames;var Nr=Object.getPrototypeOf,Lr=Object.prototype.hasOwnProperty;var Bt=(t,e)=>{for(var r in e)K(t,r,{get:e[r],enumerable:!0})},Pt=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of yr(e))!Lr.call(t,o)&&o!==r&&K(t,o,{get:()=>e[o],enumerable:!(n=Sr(e,o))||n.enumerable});return t};var u=(t,e,r)=>(r=t!=null?Or(Nr(t)):{},Pt(e||!t||!t.__esModule?K(r,"default",{value:t,enumerable:!0}):r,t)),xr=t=>Pt(K({},"__esModule",{value:!0}),t);var uo={};Bt(uo,{handleCurrentsReport:()=>hr});module.exports=xr(uo);var wt=require("debug"),Br=u(require("fs-extra")),a=(0,wt.debug)("currents"),Pr=null;function Mt(t){Pr=t}var J={};Bt(J,{getNanoid:()=>wr,userFacingNanoid:()=>Et});var lt=require("nanoid"),bt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",wr=(t=16)=>(0,lt.customAlphabet)(bt,t)(),Et=(0,lt.customAlphabet)(bt,12);var d=require("lodash");function vt(t){return t.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/?#\s]*@/i,"$1")}var Y=a.extend("ci"),Mr=(t,e)=>(0,d.set)(t,(0,d.camelCase)(e),process.env[e]),_=t=>(0,d.transform)(t,Mr,{}),br=()=>process.env.TF_BUILD&&process.env.AZURE_HTTP_USER_AGENT,vr=()=>(0,d.some)(process.env,(t,e)=>/^CODEBUILD_/.test(e)),Fr=()=>process.env.bamboo_buildNumber,Gr=()=>(0,d.some)(process.env,(t,e)=>/^CONCOURSE_/.test(e)),kr=()=>process.env.GITLAB_CI||process.env.CI_SERVER_NAME&&/^GitLab/.test(process.env.CI_SERVER_NAME),Hr=()=>!!(process.env.BUILD_ID&&process.env.PROJECT_ID&&process.env.PROJECT_NUMBER||process.env.GCP_PROJECT||process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT),jr=()=>process.env.JENKINS_URL||process.env.JENKINS_HOME||process.env.JENKINS_VERSION||process.env.HUDSON_URL||process.env.HUDSON_HOME,Kr={appveyor:"APPVEYOR",azure:br,awsCodeBuild:vr,bamboo:Fr,bitbucket:"BITBUCKET_BUILD_NUMBER",buildkite:"BUILDKITE",circle:"CIRCLECI",concourse:Gr,codeFresh:"CF_BUILD_ID",drone:"DRONE",githubActions:"GITHUB_ACTIONS",gitlab:kr,goCD:"GO_JOB_NAME",jenkins:jr,googleCloud:Hr,semaphore:"SEMAPHORE",teamcity:"TEAMCITY_VERSION",travis:"TRAVIS",netlify:"NETLIFY"};function Jr(){let{env:t}=process;return(0,d.findKey)(Kr,e=>{if((0,d.isString)(e))return t[e];if((0,d.isFunction)(e))return e()})}var Ft=()=>({appveyor:_(["APPVEYOR_JOB_ID","APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER","APPVEYOR_BUILD_VERSION","APPVEYOR_PULL_REQUEST_NUMBER","APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"]),azure:_(["AGENT_BUILDDIRECTORY","AGENT_ID","AGENT_JOBNAME","AGENT_JOBSTATUS","AGENT_MACHINENAME","AGENT_NAME","AGENT_OS","AGENT_OSARCHITECTURE","BUILD_BUILDID","BUILD_BUILDNUMBER","BUILD_BUILDURI","BUILD_CONTAINERID","BUILD_CRONSCHEDULE_DISPLAYNAME","BUILD_DEFINITIONNAME","BUILD_DEFINITIONVERSION","BUILD_QUEUEDBY","BUILD_QUEUEDBYID","BUILD_REASON","BUILD_REPOSITORY_ID","BUILD_REPOSITORY_NAME","BUILD_REPOSITORY_PROVIDER","BUILD_REPOSITORY_URI","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILD_REQUESTEDFORID","BUILD_SOURCEBRANCH","BUILD_SOURCEBRANCHNAME","BUILD_SOURCESDIRECTORY","BUILD_SOURCEVERSION","BUILD_SOURCEVERSIONAUTHOR","BUILD_SOURCEVERSIONMESSAGE","BUILD_STAGINGDIRECTORY","BUILD_TRIGGEREDBY_BUILDID","BUILD_TRIGGEREDBY_BUILDNUMBER","BUILD_TRIGGEREDBY_DEFINITIONID","BUILD_TRIGGEREDBY_DEFINITIONNAME","BUILD_TRIGGEREDBY_PROJECTID","COMMON_TESTRESULTSDIRECTORY","PIPELINE_WORKSPACE","SYSTEM_COLLECTIONID","SYSTEM_COLLECTIONURI","SYSTEM_DEFAULTWORKINGDIRECTORY","SYSTEM_DEFINITIONID","SYSTEM_HOSTTYPE","SYSTEM_JOBATTEMPT","SYSTEM_JOBDISPLAYNAME","SYSTEM_JOBID","SYSTEM_JOBNAME","SYSTEM_PHASEATTEMPT","SYSTEM_PHASEDISPLAYNAME","SYSTEM_PHASENAME","SYSTEM_PLANID","SYSTEM_PULLREQUEST_ISFORK","SYSTEM_PULLREQUEST_PULLREQUESTID","SYSTEM_PULLREQUEST_PULLREQUESTNUMBER","SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI","SYSTEM_PULLREQUEST_SOURCEBRANCH","SYSTEM_PULLREQUEST_SOURCECOMMITID","SYSTEM_PULLREQUEST_TARGETBRANCH","SYSTEM_PULLREQUEST_TARGETBRANCHNAME","SYSTEM_STAGEATTEMPT","SYSTEM_STAGEDISPLAYNAME","SYSTEM_STAGENAME","SYSTEM_TEAMFOUNDATIONCOLLECTIONURI","SYSTEM_TEAMPROJECT","SYSTEM_TEAMPROJECTID","SYSTEM_TIMELINEID"]),awsCodeBuild:_(["AWS_DEFAULT_REGION","AWS_REGION","CODEBUILD_BATCH_BUILD_IDENTIFIER","CODEBUILD_BUILD_ARN","CODEBUILD_BUILD_ID","CODEBUILD_BUILD_IMAGE","CODEBUILD_BUILD_NUMBER","CODEBUILD_BUILD_SUCCEEDING","CODEBUILD_BUILD_URL","CODEBUILD_INITIATOR","CODEBUILD_PROJECT_ARN","CODEBUILD_PUBLIC_BUILD_URL","CODEBUILD_RESOLVED_SOURCE_VERSION","CODEBUILD_SOURCE_REPO_URL","CODEBUILD_SOURCE_VERSION","CODEBUILD_SRC_DIR","CODEBUILD_START_TIME","CODEBUILD_WEBHOOK_ACTOR_ACCOUNT_ID","CODEBUILD_WEBHOOK_BASE_REF","CODEBUILD_WEBHOOK_EVENT","CODEBUILD_WEBHOOK_HEAD_REF","CODEBUILD_WEBHOOK_MERGE_COMMIT","CODEBUILD_WEBHOOK_PREV_COMMIT","CODEBUILD_WEBHOOK_TRIGGER","CODEBUILD_WEBHOOK_LABEL","CODEBUILD_WEBHOOK_RUN_ID","CODEBUILD_WEBHOOK_JOB_ID","CODEBUILD_WEBHOOK_WORKFLOW_NAME","CODEBUILD_RUNNER_OWNER","CODEBUILD_RUNNER_REPO","CODEBUILD_RUNNER_REPO_DOMAIN","CODEBUILD_RUNNER_WITH_BUILDSPEC"]),bamboo:_(["bamboo_buildNumber","bamboo_buildResultsUrl","bamboo_planRepository_repositoryUrl","bamboo_buildKey"]),bitbucket:_(["CI","BITBUCKET_WORKSPACE","BITBUCKET_REPO_SLUG","BITBUCKET_REPO_UUID","BITBUCKET_REPO_FULL_NAME","BITBUCKET_REPO_IS_PRIVATE","BITBUCKET_REPO_OWNER","BITBUCKET_REPO_OWNER_UUID","BITBUCKET_PROJECT_KEY","BITBUCKET_PROJECT_UUID","BITBUCKET_BUILD_NUMBER","BITBUCKET_PIPELINE_UUID","BITBUCKET_STEP_UUID","BITBUCKET_STEP_RUN_NUMBER","BITBUCKET_STEP_TRIGGERER_UUID","BITBUCKET_PARALLEL_STEP","BITBUCKET_PARALLEL_STEP_COUNT","BITBUCKET_CLONE_DIR","BITBUCKET_COMMIT","BITBUCKET_BRANCH","BITBUCKET_TAG","BITBUCKET_BOOKMARK","BITBUCKET_GIT_HTTP_ORIGIN","BITBUCKET_GIT_SSH_ORIGIN","BITBUCKET_PR_ID","BITBUCKET_PR_DESTINATION_BRANCH","BITBUCKET_PR_DESTINATION_COMMIT","BITBUCKET_DEPLOYMENT_ENVIRONMENT","BITBUCKET_DEPLOYMENT_ENVIRONMENT_UUID","BITBUCKET_EXIT_CODE"]),buildkite:_(["BUILDKITE_ORGANIZATION_SLUG","BUILDKITE_PIPELINE_ID","BUILDKITE_PIPELINE_NAME","BUILDKITE_PIPELINE_SLUG","BUILDKITE_PIPELINE_DEFAULT_BRANCH","BUILDKITE_REPO","BUILDKITE_SOURCE","BUILDKITE_BRANCH","BUILDKITE_TAG","BUILDKITE_COMMIT","BUILDKITE_MESSAGE","BUILDKITE_BUILD_AUTHOR","BUILDKITE_BUILD_AUTHOR_EMAIL","BUILDKITE_JOB_ID","BUILDKITE_BUILD_ID","BUILDKITE_BUILD_URL","BUILDKITE_BUILD_NUMBER","BUILDKITE_LABEL","BUILDKITE_COMMAND","BUILDKITE_STEP_ID","BUILDKITE_STEP_KEY","BUILDKITE_PARALLEL_JOB","BUILDKITE_PARALLEL_JOB_COUNT","BUILDKITE_RETRY_COUNT","BUILDKITE_COMPUTE_TYPE","BUILDKITE_CLUSTER_NAME","BUILDKITE_PULL_REQUEST","BUILDKITE_PULL_REQUEST_REPO","BUILDKITE_PULL_REQUEST_BASE_BRANCH","BUILDKITE_PULL_REQUEST_DRAFT","BUILDKITE_PULL_REQUEST_LABELS","BUILDKITE_MERGE_QUEUE_BASE_BRANCH","BUILDKITE_MERGE_QUEUE_BASE_COMMIT","BUILDKITE_REBUILT_FROM_BUILD_ID","BUILDKITE_REBUILT_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_ID","BUILDKITE_TRIGGERED_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG"]),circle:_(["CI","CIRCLECI","CIRCLE_BRANCH","CIRCLE_BUILD_NUM","CIRCLE_BUILD_URL","CIRCLE_PREVIOUS_BUILD_NUM","CIRCLE_JOB","CIRCLE_WORKFLOW_ID","CIRCLE_WORKFLOW_JOB_ID","CIRCLE_WORKFLOW_WORKSPACE_ID","CIRCLE_PIPELINE_ID","CIRCLE_ORGANIZATION_ID","CIRCLE_PROJECT_ID","CIRCLE_PROJECT_REPONAME","CIRCLE_PROJECT_USERNAME","CIRCLE_REPOSITORY_URL","CIRCLE_WORKING_DIRECTORY","CIRCLE_SHA1","CIRCLE_TAG","CIRCLE_USERNAME","CIRCLE_NODE_INDEX","CIRCLE_NODE_TOTAL","CIRCLE_PR_NUMBER","CIRCLE_PR_REPONAME","CIRCLE_PR_USERNAME","CIRCLE_PULL_REQUEST","CIRCLE_PULL_REQUESTS","CI_PULL_REQUEST"]),concourse:_(["BUILD_ID","BUILD_NAME","BUILD_JOB_NAME","BUILD_PIPELINE_NAME","BUILD_TEAM_NAME","ATC_EXTERNAL_URL"]),codeFresh:_(["CF_BUILD_ID","CF_BUILD_URL","CF_CURRENT_ATTEMPT","CF_STEP_NAME","CF_PIPELINE_NAME","CF_PIPELINE_TRIGGER_ID","CF_PULL_REQUEST_ID","CF_PULL_REQUEST_IS_FORK","CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_TARGET"]),drone:_(["DRONE_BUILD_LINK","DRONE_BUILD_NUMBER","DRONE_PULL_REQUEST"]),githubActions:_(["CI","GITHUB_ACTIONS","GITHUB_WORKFLOW","GITHUB_WORKFLOW_REF","GITHUB_WORKFLOW_SHA","GITHUB_ACTION","GITHUB_ACTION_PATH","GITHUB_ACTION_REPOSITORY","GITHUB_JOB","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_RUN_ATTEMPT","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REPOSITORY_OWNER","GITHUB_REPOSITORY_OWNER_ID","GITHUB_REF","GITHUB_REF_NAME","GITHUB_REF_TYPE","GITHUB_REF_PROTECTED","GITHUB_BASE_REF","GITHUB_HEAD_REF","GITHUB_SHA","GITHUB_ACTOR","GITHUB_ACTOR_ID","GITHUB_TRIGGERING_ACTOR","GITHUB_SERVER_URL","GITHUB_API_URL","GITHUB_GRAPHQL_URL","GITHUB_WORKSPACE","GITHUB_RETENTION_DAYS","RUNNER_OS","RUNNER_ARCH","RUNNER_NAME","RUNNER_ENVIRONMENT","RUNNER_DEBUG"]),gitlab:_(["CI_PIPELINE_ID","CI_PIPELINE_URL","CI_BUILD_ID","CI_JOB_ID","CI_JOB_URL","CI_JOB_NAME","CI_NODE_INDEX","CI_NODE_TOTAL","GITLAB_HOST","CI_PROJECT_ID","CI_PROJECT_URL","CI_REPOSITORY_URL","CI_ENVIRONMENT_URL","CI_DEFAULT_BRANCH","RUN_ATTEMPT","CI_MERGE_REQUEST_IID","CI_MERGE_REQUEST_PROJECT_URL","CI_MERGE_REQUEST_TITLE","CI_MERGE_REQUEST_SOURCE_BRANCH_NAME","CI_MERGE_REQUEST_TARGET_BRANCH_NAME","CI_OPEN_MERGE_REQUESTS"]),goCD:_(["GO_SERVER_URL","GO_ENVIRONMENT_NAME","GO_PIPELINE_NAME","GO_PIPELINE_COUNTER","GO_PIPELINE_LABEL","GO_STAGE_NAME","GO_STAGE_COUNTER","GO_JOB_NAME","GO_TRIGGER_USER","GO_REVISION","GO_TO_REVISION","GO_FROM_REVISION","GO_MATERIAL_HAS_CHANGED"]),googleCloud:_(["BUILD_ID","PROJECT_ID","REPO_NAME","BRANCH_NAME","TAG_NAME","COMMIT_SHA","SHORT_SHA"]),jenkins:_(["BRANCH_NAME","BUILD_DISPLAY_NAME","BUILD_ID","BUILD_NUMBER","BUILD_TAG","BUILD_URL","CHANGE_AUTHOR","CHANGE_AUTHOR_DISPLAY_NAME","CHANGE_AUTHOR_EMAIL","CHANGE_BRANCH","CHANGE_FORK","CHANGE_ID","CHANGE_TARGET","CHANGE_TITLE","CHANGE_URL","CI","EXECUTOR_NUMBER","JAVA_HOME","JENKINS_HOME","JENKINS_URL","JOB_BASE_NAME","JOB_NAME","JOB_URL","NODE_LABELS","NODE_NAME","RUN_ARTIFACTS_DISPLAY_URL","RUN_CHANGES_DISPLAY_URL","TAG_NAME","WORKSPACE","WORKSPACE_TMP","GIT_AUTHOR_EMAIL","GIT_AUTHOR_NAME","GIT_BRANCH","GIT_COMMIT","GIT_COMMITTER_EMAIL","GIT_COMMITTER_NAME","GIT_LOCAL_BRANCH","GIT_PREVIOUS_COMMIT","GIT_PREVIOUS_SUCCESSFUL_COMMIT","GIT_URL","ghprbActualCommit","ghprbGhRepository","ghprbPullId","ghprbPullLink","ghprbSourceBranch","ghprbTargetBranch","ghprbTriggerAuthorLogin"]),semaphore:_(["SEMAPHORE_BRANCH_ID","SEMAPHORE_BUILD_NUMBER","SEMAPHORE_CURRENT_JOB","SEMAPHORE_CURRENT_THREAD","SEMAPHORE_EXECUTABLE_UUID","SEMAPHORE_GIT_BRANCH","SEMAPHORE_GIT_DIR","SEMAPHORE_GIT_REF","SEMAPHORE_GIT_REF_TYPE","SEMAPHORE_GIT_REPO_SLUG","SEMAPHORE_GIT_SHA","SEMAPHORE_GIT_URL","SEMAPHORE_JOB_COUNT","SEMAPHORE_JOB_ID","SEMAPHORE_JOB_NAME","SEMAPHORE_JOB_UUID","SEMAPHORE_PIPELINE_ID","SEMAPHORE_PLATFORM","SEMAPHORE_PROJECT_DIR","SEMAPHORE_PROJECT_HASH_ID","SEMAPHORE_PROJECT_ID","SEMAPHORE_PROJECT_NAME","SEMAPHORE_PROJECT_UUID","SEMAPHORE_REPO_SLUG","SEMAPHORE_TRIGGER_SOURCE","SEMAPHORE_WORKFLOW_ID","PULL_REQUEST_NUMBER"]),teamcity:null,travis:_(["TRAVIS_JOB_ID","TRAVIS_BUILD_ID","TRAVIS_BUILD_WEB_URL","TRAVIS_REPO_SLUG","TRAVIS_JOB_NUMBER","TRAVIS_EVENT_TYPE","TRAVIS_COMMIT_RANGE","TRAVIS_BUILD_NUMBER","TRAVIS_PULL_REQUEST","TRAVIS_PULL_REQUEST_BRANCH","TRAVIS_PULL_REQUEST_SHA"]),netlify:_(["BUILD_ID","CONTEXT","URL","DEPLOY_URL","DEPLOY_PRIME_URL","DEPLOY_ID"])}),Yr=t=>{let e=Gt();return e?(0,d.chain)(t()).get(e).value():{}};function $r(){return(0,d.chain)(Ft()).omitBy(d.isNull).keys().value()}function Vr(t){return t&&$r().includes(t)}function Gt(){let t=Jr();return Y("detected CI provider name: %s",t),t||null}function Wr(){let t=Yr(Ft);return(0,d.mapValues)(t,e=>(0,d.isString)(e)?vt(e):e)}function kt(t){let e=Wr(),r=Gt(),n=qr(t,r);return Y("detected CI provider: %s",r),Y("detected CI params: %O",e),Y("detected CI build ID: %o",n),{params:e,provider:r,ciBuildId:n}}function qr(t,e){return t?{source:"user",value:t}:Vr(e)?{source:"server",value:null}:{source:"random",value:`auto:${Et()}`}}var Ht=require("@currents/commit-info"),jt=require("lodash");var Qr=a.extend("git"),Xr=async()=>{let t=await(0,Ht.commitInfo)();return Qr("commit: %O",t),{branch:t.branch,remoteOrigin:t.remote,authorEmail:t.email,authorName:t.author,message:t.message,sha:t.sha,ghaEventData:t.ghaEventData??null}},Kt=(0,jt.memoize)(Xr);var Jt=u(require("getos")),Yt=require("lodash"),A=require("os"),$t=require("util"),zr=async()=>{if((0,A.platform)()==="linux")try{let t=await(0,$t.promisify)(Jt.default)();return"dist"in t&&"release"in t?[t.dist,t.release].join(" - "):(0,A.release)()}catch{return(0,A.release)()}return(0,A.release)()},Zr=async()=>{let t=await zr();return{osName:(0,A.platform)(),osVersion:t,osCpus:[],osMemory:{free:(0,A.freemem)(),total:(0,A.totalmem)()}}},Vt=(0,Yt.memoize)(Zr);var Wt={name:"@currents/cmd",version:"2.1.0",main:"./dist/index.js",author:{name:"Currents Software Inc",email:"hello@currents.dev"},license:"MIT",repository:{type:"git",url:"https://github.com/currents-dev/currents-reporter"},description:"Currents CLI tools",engines:{node:">=20"},scripts:{test:"vitest",rm:"rimraf dist",lint:'TIMING=1 eslint "**/*.ts*"',types:"tsc --noEmit",build:"tsup-node --minify --dts",dev:"tsup-node --watch --dts",release:"release-it","publish:npm":"npm run rm && npm run build && ./publish.js"},devDependencies:{"@jest/reporters":"^30.4.1","@jest/types":"^30.4.1","@release-it/conventional-changelog":"^12.0.0","release-it":"^21.0.2","@types/archiver":"^6.0.3","@types/async-retry":"^1.4.9","@types/debug":"^4.1.12","@types/fs-extra":"^11.0.4","@types/getos":"^3.0.4","@types/lodash":"^4.17.16","@types/node":"^25.5.0","@types/proxy-from-env":"^1.0.4","@types/semver":"^7.5.8","@types/tmp":"^0.2.6","@types/unzipper":"^0.10.11","@types/uuid":"^10.0.0","@types/xml2js":"^0.4.14","@types/xxhashjs":"^0.2.4",jest:"^30.4.2","jest-cli":"^30.4.2","jest-config":"^30.4.2",rimraf:"^6.0.1",tsup:"^8.3.5",typescript:"^5.9.3",vitest:"^4.1.11"},dependencies:{"@commander-js/extra-typings":"^14.0.0","@currents/commit-info":"2.0.0",archiver:"^7.0.1","async-retry":"^1.3.3",axios:"1.20.0","axios-retry":"4.5.0",chalk:"^4.1.2",commander:"^14.0.0",debug:"^4.4.0",dotenv:"^17.4.2",execa:"^9.5.1","fs-extra":"^11.3.4",getos:"^3.2.1",globby:"^11.1.0","https-proxy-agent":"^7.0.4",lodash:"^4.18.1",nanoid:"^3.3.8","pretty-ms":"^7.0.1","proxy-from-env":"^1.1.0",semver:"^7.8.5","source-map-support":"^0.5.21",tmp:"^0.2.7","tmp-promise":"^3.0.3","ts-pattern":"^5.8.0",unzipper:"^0.12.3",uuid:"11.1.1",xml2js:"^0.6.2",xxhashjs:"^0.2.2"},bin:{currents:"./dist/bin/index.js","currents-cli":"./dist/bin/index.js"},files:["dist","!**/*.map","!**/*/*.map"],keywords:["cloud test dashboard","test reporter","test results","currents","currents dashboard","ci"],exports:{".":{import:"./dist/index.js",require:"./dist/index.js",types:"./dist/index.d.ts"},"./discovery/jest":{import:"./dist/services/upload/discovery/jest/reporter.js",require:"./dist/services/upload/discovery/jest/reporter.js",types:"./dist/services/upload/discovery/jest/reporter.d.ts"},"./package.json":"./package.json"},"release-it":{npm:{publish:!1},github:{release:!0,releaseName:"${npm.name} v${version}"},plugins:{"@release-it/conventional-changelog":{preset:{name:"conventionalcommits"},header:"# Changelog",ignoreVersion:!0,infile:"./CHANGELOG.md"}},git:{commitMessage:"chore: release ${npm.name} v${version}",tagName:"${npm.name}-v${version}"}}};var $=Wt.version;var ft=u(require("lodash")),en=["apiKey","recordKey","key"];function qt(t,e){return ft.default.isPlainObject(t)?ft.default.mapValues(t,(r,n)=>e.includes(n)&&r!==void 0?"*****":qt(r,e)):t}function O(t){return qt(t,en)}var rn=[];function dt(t){rn.push(t)}var h=u(require("chalk")),b=u(require("util"));var Qt=[],Xt=[];var zt=(...t)=>{let e=b.default.format(...t);dt(e),console.log(e)},nn=(...t)=>{let e=b.default.format(...t);dt(e),console.error(e)},V=zt,E=(...t)=>{let e=b.default.format(...t);return Xt.push(e),a("WARNING: ",e),zt(h.default.bgYellow.black(" WARNING "),e)};var I=(...t)=>{let e=b.default.format(...on(t));return Qt.push(e),a("ERROR: ",b.default.format(...t)),nn(h.default.bgRed.white(" ERROR "),e)};var on=t=>t.map(e=>e instanceof Error?e.message:e),W=(t=2)=>console.log(Array(t).fill("").join(`
|
|
2
|
-
`))
|
|
3
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status,payload:t.response?.config.data})})}function
|
|
4
|
-
%o`,r)}).with(404,()=>{
|
|
5
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}function
|
|
6
|
-
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}var
|
|
1
|
+
"use strict";var Fr=Object.create;var V=Object.defineProperty;var Gr=Object.getOwnPropertyDescriptor;var kr=Object.getOwnPropertyNames;var jr=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty;var Mt=(t,e)=>{for(var r in e)V(t,r,{get:e[r],enumerable:!0})},vt=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of kr(e))!Hr.call(t,o)&&o!==r&&V(t,o,{get:()=>e[o],enumerable:!(n=Gr(e,o))||n.enumerable});return t};var l=(t,e,r)=>(r=t!=null?Fr(jr(t)):{},vt(e||!t||!t.__esModule?V(r,"default",{value:t,enumerable:!0}):r,t)),Kr=t=>vt(V({},"__esModule",{value:!0}),t);var xo={};Mt(xo,{handleCurrentsReport:()=>wr});module.exports=Kr(xo);var Ft=require("debug"),Jr=l(require("fs-extra")),c=(0,Ft.debug)("currents"),Yr=null;function Gt(t){Yr=t}var W={};Mt(W,{getNanoid:()=>$r,userFacingNanoid:()=>It});var gt=require("nanoid"),kt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",$r=(t=16)=>(0,gt.customAlphabet)(kt,t)(),It=(0,gt.customAlphabet)(kt,12);var g=require("lodash");function jt(t){return t.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/?#\s]*@/i,"$1")}var q=c.extend("ci"),Vr=(t,e)=>(0,g.set)(t,(0,g.camelCase)(e),process.env[e]),_=t=>(0,g.transform)(t,Vr,{}),Wr=()=>process.env.TF_BUILD&&process.env.AZURE_HTTP_USER_AGENT,qr=()=>(0,g.some)(process.env,(t,e)=>/^CODEBUILD_/.test(e)),Qr=()=>process.env.bamboo_buildNumber,Xr=()=>(0,g.some)(process.env,(t,e)=>/^CONCOURSE_/.test(e)),zr=()=>process.env.GITLAB_CI||process.env.CI_SERVER_NAME&&/^GitLab/.test(process.env.CI_SERVER_NAME),Zr=()=>!!(process.env.BUILD_ID&&process.env.PROJECT_ID&&process.env.PROJECT_NUMBER||process.env.GCP_PROJECT||process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT),tn=()=>process.env.JENKINS_URL||process.env.JENKINS_HOME||process.env.JENKINS_VERSION||process.env.HUDSON_URL||process.env.HUDSON_HOME,en={appveyor:"APPVEYOR",azure:Wr,awsCodeBuild:qr,bamboo:Qr,bitbucket:"BITBUCKET_BUILD_NUMBER",buildkite:"BUILDKITE",circle:"CIRCLECI",concourse:Xr,codeFresh:"CF_BUILD_ID",drone:"DRONE",githubActions:"GITHUB_ACTIONS",gitlab:zr,goCD:"GO_JOB_NAME",jenkins:tn,googleCloud:Zr,semaphore:"SEMAPHORE",teamcity:"TEAMCITY_VERSION",travis:"TRAVIS",netlify:"NETLIFY"};function rn(){let{env:t}=process;return(0,g.findKey)(en,e=>{if((0,g.isString)(e))return t[e];if((0,g.isFunction)(e))return e()})}var Ht=()=>({appveyor:_(["APPVEYOR_JOB_ID","APPVEYOR_ACCOUNT_NAME","APPVEYOR_PROJECT_SLUG","APPVEYOR_BUILD_NUMBER","APPVEYOR_BUILD_VERSION","APPVEYOR_PULL_REQUEST_NUMBER","APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"]),azure:_(["AGENT_BUILDDIRECTORY","AGENT_ID","AGENT_JOBNAME","AGENT_JOBSTATUS","AGENT_MACHINENAME","AGENT_NAME","AGENT_OS","AGENT_OSARCHITECTURE","BUILD_BUILDID","BUILD_BUILDNUMBER","BUILD_BUILDURI","BUILD_CONTAINERID","BUILD_CRONSCHEDULE_DISPLAYNAME","BUILD_DEFINITIONNAME","BUILD_DEFINITIONVERSION","BUILD_QUEUEDBY","BUILD_QUEUEDBYID","BUILD_REASON","BUILD_REPOSITORY_ID","BUILD_REPOSITORY_NAME","BUILD_REPOSITORY_PROVIDER","BUILD_REPOSITORY_URI","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILD_REQUESTEDFORID","BUILD_SOURCEBRANCH","BUILD_SOURCEBRANCHNAME","BUILD_SOURCESDIRECTORY","BUILD_SOURCEVERSION","BUILD_SOURCEVERSIONAUTHOR","BUILD_SOURCEVERSIONMESSAGE","BUILD_STAGINGDIRECTORY","BUILD_TRIGGEREDBY_BUILDID","BUILD_TRIGGEREDBY_BUILDNUMBER","BUILD_TRIGGEREDBY_DEFINITIONID","BUILD_TRIGGEREDBY_DEFINITIONNAME","BUILD_TRIGGEREDBY_PROJECTID","COMMON_TESTRESULTSDIRECTORY","PIPELINE_WORKSPACE","SYSTEM_COLLECTIONID","SYSTEM_COLLECTIONURI","SYSTEM_DEFAULTWORKINGDIRECTORY","SYSTEM_DEFINITIONID","SYSTEM_HOSTTYPE","SYSTEM_JOBATTEMPT","SYSTEM_JOBDISPLAYNAME","SYSTEM_JOBID","SYSTEM_JOBNAME","SYSTEM_PHASEATTEMPT","SYSTEM_PHASEDISPLAYNAME","SYSTEM_PHASENAME","SYSTEM_PLANID","SYSTEM_PULLREQUEST_ISFORK","SYSTEM_PULLREQUEST_PULLREQUESTID","SYSTEM_PULLREQUEST_PULLREQUESTNUMBER","SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI","SYSTEM_PULLREQUEST_SOURCEBRANCH","SYSTEM_PULLREQUEST_SOURCECOMMITID","SYSTEM_PULLREQUEST_TARGETBRANCH","SYSTEM_PULLREQUEST_TARGETBRANCHNAME","SYSTEM_STAGEATTEMPT","SYSTEM_STAGEDISPLAYNAME","SYSTEM_STAGENAME","SYSTEM_TEAMFOUNDATIONCOLLECTIONURI","SYSTEM_TEAMPROJECT","SYSTEM_TEAMPROJECTID","SYSTEM_TIMELINEID"]),awsCodeBuild:_(["AWS_DEFAULT_REGION","AWS_REGION","CODEBUILD_BATCH_BUILD_IDENTIFIER","CODEBUILD_BUILD_ARN","CODEBUILD_BUILD_ID","CODEBUILD_BUILD_IMAGE","CODEBUILD_BUILD_NUMBER","CODEBUILD_BUILD_SUCCEEDING","CODEBUILD_BUILD_URL","CODEBUILD_INITIATOR","CODEBUILD_PROJECT_ARN","CODEBUILD_PUBLIC_BUILD_URL","CODEBUILD_RESOLVED_SOURCE_VERSION","CODEBUILD_SOURCE_REPO_URL","CODEBUILD_SOURCE_VERSION","CODEBUILD_SRC_DIR","CODEBUILD_START_TIME","CODEBUILD_WEBHOOK_ACTOR_ACCOUNT_ID","CODEBUILD_WEBHOOK_BASE_REF","CODEBUILD_WEBHOOK_EVENT","CODEBUILD_WEBHOOK_HEAD_REF","CODEBUILD_WEBHOOK_MERGE_COMMIT","CODEBUILD_WEBHOOK_PREV_COMMIT","CODEBUILD_WEBHOOK_TRIGGER","CODEBUILD_WEBHOOK_LABEL","CODEBUILD_WEBHOOK_RUN_ID","CODEBUILD_WEBHOOK_JOB_ID","CODEBUILD_WEBHOOK_WORKFLOW_NAME","CODEBUILD_RUNNER_OWNER","CODEBUILD_RUNNER_REPO","CODEBUILD_RUNNER_REPO_DOMAIN","CODEBUILD_RUNNER_WITH_BUILDSPEC"]),bamboo:_(["bamboo_buildNumber","bamboo_buildResultsUrl","bamboo_planRepository_repositoryUrl","bamboo_buildKey"]),bitbucket:_(["CI","BITBUCKET_WORKSPACE","BITBUCKET_REPO_SLUG","BITBUCKET_REPO_UUID","BITBUCKET_REPO_FULL_NAME","BITBUCKET_REPO_IS_PRIVATE","BITBUCKET_REPO_OWNER","BITBUCKET_REPO_OWNER_UUID","BITBUCKET_PROJECT_KEY","BITBUCKET_PROJECT_UUID","BITBUCKET_BUILD_NUMBER","BITBUCKET_PIPELINE_UUID","BITBUCKET_STEP_UUID","BITBUCKET_STEP_RUN_NUMBER","BITBUCKET_STEP_TRIGGERER_UUID","BITBUCKET_PARALLEL_STEP","BITBUCKET_PARALLEL_STEP_COUNT","BITBUCKET_CLONE_DIR","BITBUCKET_COMMIT","BITBUCKET_BRANCH","BITBUCKET_TAG","BITBUCKET_BOOKMARK","BITBUCKET_GIT_HTTP_ORIGIN","BITBUCKET_GIT_SSH_ORIGIN","BITBUCKET_PR_ID","BITBUCKET_PR_DESTINATION_BRANCH","BITBUCKET_PR_DESTINATION_COMMIT","BITBUCKET_DEPLOYMENT_ENVIRONMENT","BITBUCKET_DEPLOYMENT_ENVIRONMENT_UUID","BITBUCKET_EXIT_CODE"]),buildkite:_(["BUILDKITE_ORGANIZATION_SLUG","BUILDKITE_PIPELINE_ID","BUILDKITE_PIPELINE_NAME","BUILDKITE_PIPELINE_SLUG","BUILDKITE_PIPELINE_DEFAULT_BRANCH","BUILDKITE_REPO","BUILDKITE_SOURCE","BUILDKITE_BRANCH","BUILDKITE_TAG","BUILDKITE_COMMIT","BUILDKITE_MESSAGE","BUILDKITE_BUILD_AUTHOR","BUILDKITE_BUILD_AUTHOR_EMAIL","BUILDKITE_JOB_ID","BUILDKITE_BUILD_ID","BUILDKITE_BUILD_URL","BUILDKITE_BUILD_NUMBER","BUILDKITE_LABEL","BUILDKITE_COMMAND","BUILDKITE_STEP_ID","BUILDKITE_STEP_KEY","BUILDKITE_PARALLEL_JOB","BUILDKITE_PARALLEL_JOB_COUNT","BUILDKITE_RETRY_COUNT","BUILDKITE_COMPUTE_TYPE","BUILDKITE_CLUSTER_NAME","BUILDKITE_PULL_REQUEST","BUILDKITE_PULL_REQUEST_REPO","BUILDKITE_PULL_REQUEST_BASE_BRANCH","BUILDKITE_PULL_REQUEST_DRAFT","BUILDKITE_PULL_REQUEST_LABELS","BUILDKITE_MERGE_QUEUE_BASE_BRANCH","BUILDKITE_MERGE_QUEUE_BASE_COMMIT","BUILDKITE_REBUILT_FROM_BUILD_ID","BUILDKITE_REBUILT_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_ID","BUILDKITE_TRIGGERED_FROM_BUILD_NUMBER","BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG"]),circle:_(["CI","CIRCLECI","CIRCLE_BRANCH","CIRCLE_BUILD_NUM","CIRCLE_BUILD_URL","CIRCLE_PREVIOUS_BUILD_NUM","CIRCLE_JOB","CIRCLE_WORKFLOW_ID","CIRCLE_WORKFLOW_JOB_ID","CIRCLE_WORKFLOW_WORKSPACE_ID","CIRCLE_PIPELINE_ID","CIRCLE_ORGANIZATION_ID","CIRCLE_PROJECT_ID","CIRCLE_PROJECT_REPONAME","CIRCLE_PROJECT_USERNAME","CIRCLE_REPOSITORY_URL","CIRCLE_WORKING_DIRECTORY","CIRCLE_SHA1","CIRCLE_TAG","CIRCLE_USERNAME","CIRCLE_NODE_INDEX","CIRCLE_NODE_TOTAL","CIRCLE_PR_NUMBER","CIRCLE_PR_REPONAME","CIRCLE_PR_USERNAME","CIRCLE_PULL_REQUEST","CIRCLE_PULL_REQUESTS","CI_PULL_REQUEST"]),concourse:_(["BUILD_ID","BUILD_NAME","BUILD_JOB_NAME","BUILD_PIPELINE_NAME","BUILD_TEAM_NAME","ATC_EXTERNAL_URL"]),codeFresh:_(["CF_BUILD_ID","CF_BUILD_URL","CF_CURRENT_ATTEMPT","CF_STEP_NAME","CF_PIPELINE_NAME","CF_PIPELINE_TRIGGER_ID","CF_PULL_REQUEST_ID","CF_PULL_REQUEST_IS_FORK","CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_TARGET"]),drone:_(["DRONE_BUILD_LINK","DRONE_BUILD_NUMBER","DRONE_PULL_REQUEST"]),githubActions:_(["CI","GITHUB_ACTIONS","GITHUB_WORKFLOW","GITHUB_WORKFLOW_REF","GITHUB_WORKFLOW_SHA","GITHUB_ACTION","GITHUB_ACTION_PATH","GITHUB_ACTION_REPOSITORY","GITHUB_JOB","GITHUB_EVENT_NAME","GITHUB_EVENT_PATH","GITHUB_RUN_ID","GITHUB_RUN_NUMBER","GITHUB_RUN_ATTEMPT","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REPOSITORY_OWNER","GITHUB_REPOSITORY_OWNER_ID","GITHUB_REF","GITHUB_REF_NAME","GITHUB_REF_TYPE","GITHUB_REF_PROTECTED","GITHUB_BASE_REF","GITHUB_HEAD_REF","GITHUB_SHA","GITHUB_ACTOR","GITHUB_ACTOR_ID","GITHUB_TRIGGERING_ACTOR","GITHUB_SERVER_URL","GITHUB_API_URL","GITHUB_GRAPHQL_URL","GITHUB_WORKSPACE","GITHUB_RETENTION_DAYS","RUNNER_OS","RUNNER_ARCH","RUNNER_NAME","RUNNER_ENVIRONMENT","RUNNER_DEBUG"]),gitlab:_(["CI_PIPELINE_ID","CI_PIPELINE_URL","CI_BUILD_ID","CI_JOB_ID","CI_JOB_URL","CI_JOB_NAME","CI_NODE_INDEX","CI_NODE_TOTAL","GITLAB_HOST","CI_PROJECT_ID","CI_PROJECT_URL","CI_REPOSITORY_URL","CI_ENVIRONMENT_URL","CI_DEFAULT_BRANCH","RUN_ATTEMPT","CI_MERGE_REQUEST_IID","CI_MERGE_REQUEST_PROJECT_URL","CI_MERGE_REQUEST_TITLE","CI_MERGE_REQUEST_SOURCE_BRANCH_NAME","CI_MERGE_REQUEST_TARGET_BRANCH_NAME","CI_OPEN_MERGE_REQUESTS"]),goCD:_(["GO_SERVER_URL","GO_ENVIRONMENT_NAME","GO_PIPELINE_NAME","GO_PIPELINE_COUNTER","GO_PIPELINE_LABEL","GO_STAGE_NAME","GO_STAGE_COUNTER","GO_JOB_NAME","GO_TRIGGER_USER","GO_REVISION","GO_TO_REVISION","GO_FROM_REVISION","GO_MATERIAL_HAS_CHANGED"]),googleCloud:_(["BUILD_ID","PROJECT_ID","REPO_NAME","BRANCH_NAME","TAG_NAME","COMMIT_SHA","SHORT_SHA"]),jenkins:_(["BRANCH_NAME","BUILD_DISPLAY_NAME","BUILD_ID","BUILD_NUMBER","BUILD_TAG","BUILD_URL","CHANGE_AUTHOR","CHANGE_AUTHOR_DISPLAY_NAME","CHANGE_AUTHOR_EMAIL","CHANGE_BRANCH","CHANGE_FORK","CHANGE_ID","CHANGE_TARGET","CHANGE_TITLE","CHANGE_URL","CI","EXECUTOR_NUMBER","JAVA_HOME","JENKINS_HOME","JENKINS_URL","JOB_BASE_NAME","JOB_NAME","JOB_URL","NODE_LABELS","NODE_NAME","RUN_ARTIFACTS_DISPLAY_URL","RUN_CHANGES_DISPLAY_URL","TAG_NAME","WORKSPACE","WORKSPACE_TMP","GIT_AUTHOR_EMAIL","GIT_AUTHOR_NAME","GIT_BRANCH","GIT_COMMIT","GIT_COMMITTER_EMAIL","GIT_COMMITTER_NAME","GIT_LOCAL_BRANCH","GIT_PREVIOUS_COMMIT","GIT_PREVIOUS_SUCCESSFUL_COMMIT","GIT_URL","ghprbActualCommit","ghprbGhRepository","ghprbPullId","ghprbPullLink","ghprbSourceBranch","ghprbTargetBranch","ghprbTriggerAuthorLogin"]),semaphore:_(["SEMAPHORE_BRANCH_ID","SEMAPHORE_BUILD_NUMBER","SEMAPHORE_CURRENT_JOB","SEMAPHORE_CURRENT_THREAD","SEMAPHORE_EXECUTABLE_UUID","SEMAPHORE_GIT_BRANCH","SEMAPHORE_GIT_DIR","SEMAPHORE_GIT_REF","SEMAPHORE_GIT_REF_TYPE","SEMAPHORE_GIT_REPO_SLUG","SEMAPHORE_GIT_SHA","SEMAPHORE_GIT_URL","SEMAPHORE_JOB_COUNT","SEMAPHORE_JOB_ID","SEMAPHORE_JOB_NAME","SEMAPHORE_JOB_UUID","SEMAPHORE_PIPELINE_ID","SEMAPHORE_PLATFORM","SEMAPHORE_PROJECT_DIR","SEMAPHORE_PROJECT_HASH_ID","SEMAPHORE_PROJECT_ID","SEMAPHORE_PROJECT_NAME","SEMAPHORE_PROJECT_UUID","SEMAPHORE_REPO_SLUG","SEMAPHORE_TRIGGER_SOURCE","SEMAPHORE_WORKFLOW_ID","PULL_REQUEST_NUMBER"]),teamcity:null,travis:_(["TRAVIS_JOB_ID","TRAVIS_BUILD_ID","TRAVIS_BUILD_WEB_URL","TRAVIS_REPO_SLUG","TRAVIS_JOB_NUMBER","TRAVIS_EVENT_TYPE","TRAVIS_COMMIT_RANGE","TRAVIS_BUILD_NUMBER","TRAVIS_PULL_REQUEST","TRAVIS_PULL_REQUEST_BRANCH","TRAVIS_PULL_REQUEST_SHA"]),netlify:_(["BUILD_ID","CONTEXT","URL","DEPLOY_URL","DEPLOY_PRIME_URL","DEPLOY_ID"])}),nn=t=>{let e=Kt();return e?(0,g.chain)(t()).get(e).value():{}};function on(){return(0,g.chain)(Ht()).omitBy(g.isNull).keys().value()}function sn(t){return t&&on().includes(t)}function Kt(){let t=rn();return q("detected CI provider name: %s",t),t||null}function an(){let t=nn(Ht);return(0,g.mapValues)(t,e=>(0,g.isString)(e)?jt(e):e)}function Jt(t){let e=an(),r=Kt(),n=cn(t,r);return q("detected CI provider: %s",r),q("detected CI params: %O",e),q("detected CI build ID: %o",n),{params:e,provider:r,ciBuildId:n}}function cn(t,e){return t?{source:"user",value:t}:sn(e)?{source:"server",value:null}:{source:"random",value:`auto:${It()}`}}var Yt=require("@currents/commit-info"),$t=require("lodash");var pn=c.extend("git"),un=async()=>{let t=await(0,Yt.commitInfo)();return pn("commit: %O",t),{branch:t.branch,remoteOrigin:t.remote,authorEmail:t.email,authorName:t.author,message:t.message,sha:t.sha,ghaEventData:t.ghaEventData??null}},Tt=(0,$t.memoize)(un);var Vt=l(require("getos")),Wt=require("lodash"),y=require("os"),qt=require("util"),ln=async()=>{if((0,y.platform)()==="linux")try{let t=await(0,qt.promisify)(Vt.default)();return"dist"in t&&"release"in t?[t.dist,t.release].join(" - "):(0,y.release)()}catch{return(0,y.release)()}return(0,y.release)()},mn=async()=>{let t=await ln();return{osName:(0,y.platform)(),osVersion:t,osCpus:[],osMemory:{free:(0,y.freemem)(),total:(0,y.totalmem)()}}},Qt=(0,Wt.memoize)(mn);var Xt={name:"@currents/cmd",version:"2.3.0",main:"./dist/index.js",author:{name:"Currents Software Inc",email:"hello@currents.dev"},license:"MIT",repository:{type:"git",url:"https://github.com/currents-dev/currents-reporter"},description:"Currents CLI tools",engines:{node:">=20"},scripts:{test:"vitest",rm:"rimraf dist",lint:'TIMING=1 eslint "**/*.ts*"',types:"tsc --noEmit",build:"tsup-node --minify --dts",dev:"tsup-node --watch --dts",release:"release-it","publish:npm":"npm run rm && npm run build && ./publish.js"},devDependencies:{"@jest/reporters":"^30.4.1","@jest/types":"^30.4.1","@release-it/conventional-changelog":"^12.0.0","release-it":"^21.0.2","@types/archiver":"^6.0.3","@types/async-retry":"^1.4.9","@types/debug":"^4.1.12","@types/fs-extra":"^11.0.4","@types/getos":"^3.0.4","@types/lodash":"^4.17.16","@types/node":"^25.5.0","@types/proxy-from-env":"^1.0.4","@types/semver":"^7.5.8","@types/tmp":"^0.2.6","@types/unzipper":"^0.10.11","@types/uuid":"^10.0.0","@types/xml2js":"^0.4.14","@types/xxhashjs":"^0.2.4",jest:"^30.4.2","jest-cli":"^30.4.2","jest-config":"^30.4.2",rimraf:"^6.0.1",tsup:"^8.3.5",typescript:"^5.9.3",vitest:"^4.1.11"},dependencies:{"@commander-js/extra-typings":"^14.0.0","@currents/commit-info":"2.0.0","@currents/rules":"^0.1.0",archiver:"^7.0.1","async-retry":"^1.3.3",axios:"1.20.0","axios-retry":"4.5.0",chalk:"^4.1.2",commander:"^14.0.0",debug:"^4.4.0",dotenv:"^17.4.2",execa:"^9.5.1","fs-extra":"^11.3.4",getos:"^3.2.1",globby:"^11.1.0","https-proxy-agent":"^7.0.4",lodash:"^4.18.1",nanoid:"^3.3.8","pretty-ms":"^7.0.1","proxy-from-env":"^1.1.0",semver:"^7.8.5","source-map-support":"^0.5.21",tmp:"^0.2.7","tmp-promise":"^3.0.3","ts-pattern":"^5.8.0",unzipper:"^0.12.3",uuid:"11.1.1",xml2js:"^0.6.2",xxhashjs:"^0.2.2"},bin:{currents:"./dist/bin/index.js","currents-cli":"./dist/bin/index.js"},files:["dist","docs","!**/*.map","!**/*/*.map"],keywords:["cloud test dashboard","test reporter","test results","currents","currents dashboard","ci"],exports:{".":{import:"./dist/index.js",require:"./dist/index.js",types:"./dist/index.d.ts"},"./discovery/jest":{import:"./dist/services/upload/discovery/jest/reporter.js",require:"./dist/services/upload/discovery/jest/reporter.js",types:"./dist/services/upload/discovery/jest/reporter.d.ts"},"./package.json":"./package.json"},"release-it":{npm:{publish:!1},github:{release:!0,releaseName:"${npm.name} v${version}"},plugins:{"@release-it/conventional-changelog":{preset:{name:"conventionalcommits"},header:"# Changelog",ignoreVersion:!0,infile:"./CHANGELOG.md"}},git:{commitMessage:"chore: release ${npm.name} v${version}",tagName:"${npm.name}-v${version}"}}};var Q=Xt.version;var Rt=l(require("lodash")),dn=["apiKey","recordKey","key"];function zt(t,e){return Rt.default.isPlainObject(t)?Rt.default.mapValues(t,(r,n)=>e.includes(n)&&r!==void 0?"*****":zt(r,e)):t}function N(t){return zt(t,dn)}var En=[];function _t(t){En.push(t)}var U=l(require("chalk")),F=l(require("util"));var Zt=[],te=[];var ee=(...t)=>{let e=F.default.format(...t);_t(e),console.log(e)},gn=(...t)=>{let e=F.default.format(...t);_t(e),console.error(e)},G=ee,d=(...t)=>{let e=F.default.format(...t);return te.push(e),c("WARNING: ",e),ee(U.default.bgYellow.black(" WARNING "),e)};var R=(...t)=>{let e=F.default.format(...In(t));return Zt.push(e),c("ERROR: ",F.default.format(...t)),gn(U.default.bgRed.white(" ERROR "),e)};var In=t=>t.map(e=>e instanceof Error?e.message:e),X=(t=2)=>console.log(Array(t).fill("").join(`
|
|
2
|
+
`)),ls=U.default.cyan,ms=U.default.blueBright,fs=U.default.red,ds=U.default.yellow,Es=U.default.green,gs=U.default.gray,Is=U.default.white,Ts=U.default.black,Rs=U.default.magenta,k=U.default.dim,_s=U.default.bold;var j=l(require("fs-extra")),Ct=require("path"),Rn=require("uuid");async function M(t){try{return await j.default.readJson(t)}catch(e){throw R("Error while reading JSON file: %s",t,e),R}}async function ht(t,e){try{return await j.default.writeFile(t,e,"utf8"),t}catch(r){throw R(`Error writing file at ${t}:`,r),r}}async function re(t){try{return await j.default.ensureDir(t),c("Folder created",t),t}catch(e){throw R(`Failed to create folder at ${t}:`,e),e}}async function ne(t,e){try{return await j.default.ensureDir((0,Ct.dirname)(e)),await j.default.copy(t,e),c("File copied from %s to %s",t,e),e}catch(r){throw R(`Failed to copy file from ${t} to ${e}:`,r),r}}var oe=l(require("crypto"));function se(t){return oe.createHash("sha256").update(t).digest("base64").slice(0,8).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var Pr=l(require("axios")),bt=l(require("fs-extra")),ft=l(require("path")),Br=l(require("semver"));var Ae=l(require("lodash"));var Ee=l(require("axios")),ge=l(require("axios-retry")),yt=l(require("lodash"));var ie=()=>process.env.CURRENTS_API_URL??"https://cy.currents.dev",ae=()=>process.env.CURRENTS_REST_API_URL??"https://api.currents.dev",ce=()=>3e4;var z=require("axios"),At=l(require("pretty-ms"));var ue=c.extend("http"),pe=[3*1e3,15*1e3,30*1e3],le=60*1e3;function Ut(t,e=Date.now()){let r=t?.response?.headers?.["retry-after"];if(r==null||r==="")return;let n=Number(r);if(Number.isFinite(n))return Math.max(0,n*1e3);let o=Date.parse(String(r));return Number.isNaN(o)?void 0:Math.max(0,o-e)}var Z=(t,e)=>{let r=pe[Math.min(t,pe.length)-1],n=Ut(e);return n===void 0?r:Math.min(Math.max(n,r),le)},Dt=t=>(ue("isRetriableError: %o",{message:t.message,code:"code"in t?t.code:void 0,status:"response"in t?t.response?.status:void 0,headers:"response"in t?t.response?.headers:void 0,data:"response"in t?t.response?.data:void 0,isAxiosError:(0,z.isAxiosError)(t)}),"code"in t&&t.code&&["ECONNABORTED","ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENETRESET"].includes(t.code)?!0:(0,z.isAxiosError)(t)?[408,429,502,503,504].includes(t.response?.status??0):!1),_n=["get","head","options","put","delete"],me=t=>{if(!(0,z.isAxiosError)(t))return!1;let e=t.response?.status;if(e===429){let r=Ut(t);return r===void 0||r<=le}return _n.includes(t.config?.method?.toLowerCase()??"get")?Dt(t):e===408||t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"},tt=()=>3;function fe(t,e,r){ue("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,At.default)(Z(t,e)??0),t,tt()),d("Network request '%s' failed: '%s'. Next attempt is in %s (%d/%d).",`${r.method?.toUpperCase()} ${r.url}`,e.message,(0,At.default)(Z(t,e)??0),t,tt())}var St=c.extend("http");var Ot={api:null,restApi:null};function Cn(t){let e=t==="api"?ie():ae();St("client base url: %s",e);let r=Ee.default.create({baseURL:e,timeout:ce(),transitional:{clarifyTimeoutError:!0}});return r.interceptors.request.use(n=>{let o=n["axios-retry"]?.retryCount??0;n.headers.set({"x-cmd-version":Q}),n.headers.get("Content-Type")||n.headers.set("Content-Type","application/json");let s={...yt.default.pick(n,"method","url","headers"),baseURL:e,data:Buffer.isBuffer(n.data)?"buffer":n.data,params:n.params};return o?St("network request retry: %o",de({...s,baseURL:e,isRetry:!0})):St("network request: %o",de(s)),n}),(0,ge.default)(r,{retries:tt(),retryCondition:t==="restApi"?me:Dt,retryDelay:(n,o)=>Z(n,o),shouldResetTimeout:!0,onRetry:fe}),r}function et(t){return Ot[t]===null&&(Ot[t]=Cn(t)),Ot[t]}function de(t){return{method:t.method,baseURL:t.baseURL,url:t.url,data:t.isRetry?"<retry>":hn(t.data),params:t.isRetry?"<retry>":t.params,headers:{...t.headers,Authorization:"Bearer ***","x-currents-key":"***"}}}function hn(t){if(t?.results?.raw)return N({...t,results:{...t.results,raw:"***"}});if(typeof t=="string")try{return N(JSON.parse(t))}catch{return t}return yt.default.isPlainObject(t)?N(t):t}var Re=require("axios"),_e=l(require("lodash")),A=require("ts-pattern");function Ce(t){(0,A.match)(t).when(Re.isAxiosError,An).otherwise(()=>{d("Unexpected error while sending network request: %s",t)})}function An(t){return(0,A.match)(t).with({code:"ECONNABORTED"},()=>{d("Network connection aborted")}).with({code:"ECONNREFUSED"},()=>{d("Network connection aborted")}).with({code:"ECONNRESET"},()=>{d("Network connection reset")}).with({code:"ETIMEDOUT"},()=>{d("Network connection timeout")}).with({response:A.P.not(A.P.nullish)},e=>{Un(e,{status:e.response.status,data:e.response.data})}).otherwise(e=>{d(`[currents] Unexpected network error: %s
|
|
3
|
+
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status,payload:t.response?.config.data})})}function Un(t,{status:e,data:r}){(0,A.match)(e).with(401,()=>{d(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 401 Unauthorized Request from cloud service`)}).with(400,()=>{d(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 400 Bad Request from cloud service:
|
|
4
|
+
%o`,r)}).with(404,()=>{d(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 404 Not Found from cloud service`)}).with(429,()=>{d(`[currents] ${t.response?.config.method} ${t.response?.config.url} - 429 Too Many Requests from cloud service`)}).with(422,()=>{Dn(t,r)}).otherwise(()=>{d(`[currents] Unexpected network response: %s
|
|
5
|
+
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}function Dn(t,e){(0,A.match)(e).with({code:Ie.MISSING_SUITE,message:A.P.string,errors:A.P.array(A.P.string)},async r=>{let{message:n,errors:o}=r;X(1),R(...Te(n,o))}).with({code:Ie.RUN_EXPIRED,message:A.P.string},r=>{d(r.message)}).with({message:A.P.string,errors:A.P.array(A.P.string)},r=>{let{message:n,errors:o}=r;X(1),d(...Te(n,o)),X(1)}).otherwise(()=>{d(`[currents] Unexpected network response: %s
|
|
6
|
+
%O`,t.message,{method:t.response?.config.method,url:t.response?.config.url,status:t.response?.status})})}var Ie={RUN_CANCELLED:"RUN_CANCELLED",RUN_EXPIRED:"RUN_EXPIRED",MISSING_SUITE:"MISSING_SUITE"};function Te(t,e){return _e.default.isString(t)?e?.length===0?[t]:[t,`
|
|
7
7
|
${(e??[]).map(r=>` - ${r}`).join(`
|
|
8
8
|
`)}
|
|
9
|
-
`]:["Unexpected network error"]}var _e=a.extend("http");async function G(t,e,r=z){try{let n=await r(t).request(e);return _e("network response: %o",{...Re.default.omit(n,"request","config"),url:n.config.url,method:n.config.method}),n}catch(n){let o=n;throw _e("network error: %o",{code:o.code,message:o.message,url:o.config?.url,method:o.config?.method,status:o.response?.status,headers:o.response?.headers,data:o.response?.data}),Te(o),o}}var ei=a.extend("api");var ci=a.extend("api");var he=require("util"),Ue=require("zlib");var Ce=a.extend("api"),fn=(0,he.promisify)(Ue.gzip);async function De(t){try{Ce("Run params: %o",O(t));let e=await dn(JSON.stringify(t));return G("api",{url:"v1/runs",method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":"gzip"},data:e}).then(r=>r.data)}catch(e){throw Ce("Failed to create the run:",e),e}}async function dn(t){try{return await fn(t)}catch(e){throw I("Failed to compress run payload:",e),e}}var hi=a.extend("api");var gn=require("axios");var xi=a.extend("api");var Dt={apiKey:{name:"API key",env:"CURRENTS_API_KEY",cli:"--api-key"},recordKey:{name:"Record key",env:"CURRENTS_RECORD_KEY",cli:"--key"},projectId:{name:"Project ID",env:"CURRENTS_PROJECT_ID",cli:"--project-id"},ciBuildId:{name:"CI build ID",env:"CURRENTS_CI_BUILD_ID",cli:"--ci-build-id"},machineId:{name:"Machine ID",env:"CURRENTS_MACHINE_ID",cli:"--machine-id"},tag:{name:"Tag",cli:"--tag"},debug:{name:"Debug",env:"CURRENTS_DEBUG",cli:"--debug"}};var{debug:In,ciBuildId:Tn,recordKey:_n,projectId:Rn,machineId:Cn}=Dt,hn={debug:In,ciBuildId:Tn,recordKey:_n,projectId:Rn,machineId:Cn,tag:{...Dt.tag,env:"CURRENTS_TAG"},disableTitleTags:{name:"Disable title tags",env:"CURRENTS_DISABLE_TITLE_TAGS",cli:"--disable-title-tags"},removeTitleTags:{name:"Remove title tags",env:"CURRENTS_REMOVE_TITLE_TAGS",cli:"--remove-title-tags"},reportDir:{name:"Report folder",env:"CURRENTS_REPORT_DIR",cli:"--report-dir"}};var ca=a.extend("config");var Un=null;function Oe(){return Un}var Ot=u(require("fs-extra")),N=require("path");var Dn=u(require("path")),Se={".png":{type:"screenshot",contentType:"image/png"},".jpg":{type:"screenshot",contentType:"image/jpeg"},".jpeg":{type:"screenshot",contentType:"image/jpeg"},".webp":{type:"screenshot",contentType:"image/webp"},".gif":{type:"screenshot",contentType:"image/gif"},".mp4":{type:"video",contentType:"video/mp4"},".webm":{type:"video",contentType:"video/webm"},".svg":{type:"attachment",contentType:"image/svg+xml"},".log":{type:"attachment",contentType:"text/plain"},".txt":{type:"attachment",contentType:"text/plain"},".yml":{type:"attachment",contentType:"text/plain"},".yaml":{type:"attachment",contentType:"text/plain"},".md":{type:"attachment",contentType:"text/markdown"},".html":{type:"attachment",contentType:"text/html"},".csv":{type:"attachment",contentType:"text/csv"},".json":{type:"attachment",contentType:"application/json"},".pdf":{type:"attachment",contentType:"application/pdf"},".gz":{type:"attachment",contentType:"application/gzip"},".viewhierarchy":{type:"attachment",contentType:"application/xml"}};var ye=u(require("fs-extra")),Ne=require("path"),At=a.extend("detox"),An="detox.json";function Le(t){return[...t].sort((e,r)=>(e.session??0)-(r.session??0)||e.invocations-r.invocations)}async function xe(t){let e=(0,Ne.join)(t,An);try{let r=await ye.default.readJson(e);if(typeof r?.artifactsRootDir!="string"||!Array.isArray(r?.tests)){At("Unexpected Detox manifest contents at %s",e);return}return At("Detox manifest: %o",r),r}catch{At("No Detox manifest at %s",e);return}}var Z=require("path"),On=a.extend("detox"),Be=255,Sn=/[/\\?<>:*|"$\u0000-\u001f]/g,Pe=4;function we(t){return yn(t)??Nn(t)}function yn({rootDir:t,fullName:e,status:r,invocations:n}){try{let o=require.resolve("detox/src/artifacts/utils/ArtifactPathBuilder",{paths:[process.cwd()]}),s=require(o),c=new s({rootDir:t});return(0,Z.dirname)(c.buildPathForTestArtifact("test.mp4",{fullName:e,status:r,invocations:n}))}catch(o){On("Detox path builder is not available: %o",o);return}}function Nn({rootDir:t,fullName:e,status:r,invocations:n}){let o=xn(r),s=n>1?` (${n})`:"",c=e.slice(-Be+o.length+s.length),p=`${o}${c}${s}`.replace(Sn,"_");return(0,Z.join)(t,Ln(p,Be))}function Ln(t,e){let r=Buffer.from(t,"utf8");return r.length<=e?t:r.subarray(0,e).toString("utf8").replace(/\uFFFD$/,"")}function xn(t){switch(t){case"passed":return"\u2713 ";case"failed":return"\u2717 ";default:return""}}var be=u(require("fs-extra")),ve=require("path"),Me=a.extend("detox"),tt="detox.trace.json",Bn="ws-client-invocation";async function Fe(t){let e=(0,ve.join)(t,tt),r=new Map,n;try{n=await be.default.readJson(e)}catch{return Me("No Detox trace at %s",e),r}if(!Array.isArray(n))return Me("Unexpected Detox trace contents at %s",e),r;let o=Pn(n);return Mn(n).forEach(({pid:c,ts:p,step:l})=>{o.filter(f=>f.pid===c&&p>=f.startTs&&p<=f.endTs).sort((f,R)=>f.startTs-R.startTs).pop()?.steps.push(l)}),o.forEach(({fullName:c,invocations:p,steps:l})=>{let m=r.get(c)??[];m.push({fullName:c,invocations:p,steps:l.sort((f,R)=>+new Date(f.startTime)-+new Date(R.startTime))}),r.set(c,m)}),r}function Pn(t){let e=new Map,r=[];t.forEach(o=>{let s=`${o.pid}:${o.tid}`,c=e.get(s)??[];if(e.set(s,c),o.ph==="B"){c.push(wn(o));return}if(o.ph==="E"){let p=c.pop();p&&r.push({...p,endTs:Number(o.ts)})}});let n=[...e.values()].flatMap(o=>o.filter(s=>s!==void 0));return[...r,...n]}function wn(t){let e=t.args?.fullName;if(!(t.args?.context!=="test"||typeof e!="string"))return{fullName:e,invocations:Number(t.args?.invocations??1),pid:Number(t.pid),startTs:Number(t.ts),endTs:Number.MAX_SAFE_INTEGER,steps:[]}}function Mn(t){let e=new Map,r=[];return t.forEach(n=>{if(!n.cat?.includes(Bn))return;let o=`${n.pid}:${n.tid}`,s=e.get(o)??[];if(n.ph==="B"){s.push({name:n.name??"action",cat:n.cat,ts:Number(n.ts)}),e.set(o,s);return}if(n.ph==="E"){let c=s.pop();if(!c)return;r.push({pid:Number(n.pid),ts:c.ts,step:{title:c.name,category:"detox",startTime:new Date(c.ts/1e3).toISOString(),duration:Math.round((Number(n.ts)-c.ts)/1e3),steps:[]}})}}),r}var H=a.extend("detox"),Ge="artifacts",bn=[".mp4",".png",".jpg",".log",".txt",".json",".viewhierarchy"],vn=t=>{let e=(0,N.extname)(t);return bn.includes(e)?Se[e]:void 0};async function ke({instances:t,reportDir:e,manifest:r}){let n=Gn(r),o=await Fe(r.artifactsRootDir),s=await Zt((0,N.join)(e,Ge)),c={artifacts:0,steps:0};for(let p of t)for(let l of p.results.tests){let m=n.get(l.testId);if(!m){H("No Detox manifest entry for %s",l.testId);continue}await kn({test:l,manifestTest:m,rootDir:r.artifactsRootDir,artifactsDir:s,traceSlices:o.get(m.fullName)??[],result:c})}return c.artifacts+=await Fn({instances:t,rootDir:r.artifactsRootDir,artifactsDir:s}),c}async function Fn({instances:t,rootDir:e,artifactsDir:r}){if(!await Ot.default.pathExists((0,N.join)(e,tt)))return 0;let[n]=await He(e,[tt],r),o=t.map(s=>s.results.tests[0]).filter(s=>s!==void 0);return o.forEach(s=>{s.artifacts=[...s.artifacts??[],n]}),o.length}function Gn(t){let e=new Map;return t.tests.forEach(r=>{e.set(r.fullName,[...e.get(r.fullName)??[],r.testId])}),new Map(t.tests.filter(r=>{let n=e.get(r.fullName)?.length===1;return n||H("Ambiguous Detox test name, skipping: %s",r.fullName),n}).map(r=>[r.testId,r]))}async function kn({test:t,manifestTest:e,rootDir:r,artifactsDir:n,traceSlices:o,result:s}){let c=[...t.attempts].sort((m,f)=>m.attempt-f.attempt),p=Le(e.attempts),l=1;for(let[m,f]of p.entries()){let R=c[m];if(!R){H("No reported attempt %d of %s",m,e.fullName);continue}let g=await Hn({fullName:e.fullName,status:f.status,rootDir:r,artifactsDir:n,fromInvocation:l});g&&(l=g.invocation+1,R.artifacts=[...R.artifacts??[],...g.artifacts],s.artifacts+=g.artifacts.length);let S=Kn(o,m,g?.invocation);S.length&&(R.steps=[...R.steps??[],...S],s.steps+=S.length)}}async function Hn({fullName:t,status:e,rootDir:r,artifactsDir:n,fromInvocation:o}){for(let s=o;s<o+Pe;s++){let c=we({rootDir:r,fullName:t,status:e,invocations:s}),p=await jn(c);if(p)return{invocation:s,artifacts:await He(c,p,n)}}H("No Detox artifacts for %s [%s]",t,e)}async function jn(t){try{return(await Ot.default.readdir(t)).sort()}catch{return}}async function He(t,e,r){let n=[];for(let o of e){let s=vn(o);if(!s){H("Skipping unsupported Detox artifact %s",o);continue}let c=(0,N.join)(t,o),p=`${re(c)}${(0,N.extname)(o)}`;await te(c,(0,N.join)(r,p)),n.push({...s,path:(0,N.join)(Ge,p),name:o})}return n}function Kn(t,e,r){return((r===void 0?void 0:t.find(s=>s.invocations===r))??[...t].sort((s,c)=>s.invocations-c.invocations)[e])?.steps??[]}var x=class{constructor(e){this.config=e}async getFullTestSuite(){return[]}};var Yn=u(require("crypto"));var je=u(require("fs-extra")),Jn=u(require("path"));async function et(t){let e=await je.default.pathExists(t);if(!e)throw new Error("File does not exist");return e}function Ke(){return"root"}function Je(t){let e=(t.join(" ").match(/@(\S+)/g)??[]).filter(Boolean).map(r=>r);return Array.from(new Set([...e].map(r=>r.trim()).map(r=>r.replace("@",""))))}var $n=/^[0-9a-f]{32}$/;function Ye(t){let e=[];for(let r of t){let n=e.find(o=>o.name===r.groupId);n||(n={name:r.groupId,tags:[],tests:[]},e.push(n)),n.tests.push(...Ve(r))}return e.length===1&&$n.test(e[0].name)&&(e[0].name=Ke()),e}function $e(t,e,r){let n=[];for(let{projectId:o,spec:s}of e){let c=r.find(l=>l.spec===s&&l.groupId===o)??(t.length===1?r.find(l=>l.spec===s):void 0);if(!c){n.push(s);continue}let p=t.length===1?t[0]:t.find(l=>l.name===o);p||(p={name:o,tags:[],tests:[]},t.push(p)),p.tests.push(...Ve(c))}return n}function Ve(t){return t.results.tests.map(e=>({spec:t.spec,testId:e.testId,title:e.title,tags:e.tags??Je(e.title)}))}var cr=u(require("fs-extra")),pr=u(require("tmp"));var ir=require("lodash");function We(t){let e=[];for(let[r,n]of Object.entries(t))r==="_"||r==="$0"||r.includes("-")||(typeof n=="boolean"?n&&e.push(`--${r}`):Array.isArray(n)?n.forEach(o=>{e.push(`--${r}=${o}`)}):e.push(`--${r}=${n}`));return e.join(" ")}var qe=require("lodash"),Vn=["bail","clearCache","collectCoverage","collectCoverageFrom","color","colors","config","coverage","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","debug","detectLeaks","detectOpenHandles","errorOnDeprecated","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","notify","notifyMode","openHandlesTimeout","outputFile","reporters","runner","shard","showConfig","showSeed","silent","testFailureExitCode","testNamePattern","verbose","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll","watchPathIgnorePatterns","watchman"];function Qe(t){return(0,qe.omit)(t,...Vn)}var or=u(require("fs")),st=require("lodash"),yt=u(require("path"));var St=u(require("fs")),rt=require("module"),nt=u(require("path")),Xe=u(require("semver")),Wn=">=29.5.0";function qn(){let t=(0,rt.createRequire)(nt.default.join(process.cwd(),"package.json"));if(Qn(t)==="jest-cli")return t.resolve("jest-cli");try{return(0,rt.createRequire)(t.resolve("jest")).resolve("jest-cli")}catch{}try{return t.resolve("jest-cli")}catch{throw new Error(`Jest discovery needs the "jest" package, and it is not installed in ${process.cwd()}. Run the command from the folder of the project that ran the tests, or install Jest 29.5 or later: npm install --save-dev jest`)}}function Qn(t){for(let e of t.resolve.paths("jest")??[]){if(St.default.existsSync(nt.default.join(e,"jest","package.json")))return"jest";if(St.default.existsSync(nt.default.join(e,"jest-cli","package.json")))return"jest-cli"}return null}function ze(){let t=(0,rt.createRequire)(qn()),{version:e}=t("jest-cli/package.json");if(!Xe.default.satisfies(e,Wn,{includePrerelease:!0}))throw new Error(`Jest discovery needs Jest 29.5 or later, and ${process.cwd()} has Jest ${e}. Update Jest: npm install --save-dev jest@latest`);return t}function Ze(){return ze()("jest-cli")}function tr(){return ze()("jest-config")}function ot(t,e){return(...r)=>new Promise((n,o)=>{let s=0,c=()=>{s++;try{let p=t(...r);n(p)}catch(p){if(s>=e.length)o(p);else{let l=e[s-1];setTimeout(c,l)}}};c()})}var er=a.extend("jest-discovery");function rr(t){return["testEnvironment","globalSetup","globalTeardown"].some(e=>String(t[e]??"").includes("detox"))}function nr(t){return{...(0,st.omit)(t,["globalSetup","globalTeardown","testEnvironmentOptions"]),testEnvironment:"node"}}async function sr(t,e){let r=e.detox;try{let{readInitialOptions:n}=tr(),{config:o,configPath:s}=await n(t);r||=[o,...o.projects??[]].some(g=>typeof g!="string"&&rr(g));let c=["collectCoverage","collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","errorOnDeprecated","forceCoverageMatch","notify","notifyMode","openHandlesTimeout","reporters","runner","showSeed","testFailureExitCode","verbose","watchPathIgnorePatterns","watchPlugins","watchman","bail","clearCache","color","colors","debug","detectLeaks","detectOpenHandles","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","outputFile","shard","showConfig","silent","testNamePattern","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll"],p=["collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","detectLeaks","detectOpenHandles","errorOnDeprecated","forceCoverageMatch","openHandlesTimeout","runner","watchPathIgnorePatterns"],l=g=>e.detox||rr(g),m=(0,st.omit)(o,c);if(l(m)&&(m=nr(m)),m.projects&&(m.projects=m.projects.map(g=>{if(typeof g=="string")return g;let S=(0,st.omit)(g,p);return l(S)?nr(S):S})),m.rootDir&&Object.keys(m).length===1)return null;let f=yt.default.resolve(s?yt.default.dirname(s):process.cwd(),`.jest-scanner-${new Date().getTime()}.config.cjs`),R=`module.exports=${JSON.stringify(m,null,2)}`;return er("configFileContent: %O",R),or.default.writeFileSync(f,R),await ot(et,[200,200,200,200,200,1e3])(f),f}catch(n){if(er("error %o",n),r)throw new Error(`Failed to recreate the Jest config for discovery: ${n.message}`);return I("Failed to recreate the config file"),null}}async function ar(t,e){let r="!!##ThisPatternWillNotMatchAnyTestName##!!",n=t.options,o=Qe(n),s=We(o),c=n.config,p=await sr(c,e);return{cliArgs:[s,"--testNamePattern",r,"--reporters",require.resolve("@currents/cmd/discovery/jest"),"--shard=1/1","--testFailureExitCode=0",p?`--config=${p}`:"",...t.args].filter(m=>!(0,ir.isEmpty)(m)),configFilePath:p}}var Xn=a.extend("jest-discovery");async function ur(t,e){console.time(v("@currents/jest:fullTestSuite-ready"));let{run:r}=Ze(),{cliArgs:n,configFilePath:o}=await ar(t,e);try{let s=pr.default.fileSync({postfix:".json"});return Xn("running scanner: %o",n),process.env.CURRENTS_DISCOVERY_PATH=s.name,await r(n.concat(["--openHandlesTimeout=0"])),await ot(et,Array.from({length:300},()=>100))(s.name),console.timeEnd(v("@currents/jest:fullTestSuite-ready")),await M(s.name)}catch(s){return I("Failed to obtain the jest full test suite:",s),{fullTestSuite:[],specsWithoutResults:[]}}finally{o&&cr.default.unlinkSync(o)}}var mr=a.extend("jest-discovery"),it=class extends x{constructor(r,n){super(r);this.instances=n}async getFullTestSuite(){if(!this.config.frameworkConfig?.shard)return mr("Not a sharded run, listing the tests of the results"),Ye(this.instances);let{fullTestSuite:r,specsWithoutResults:n}=await ur(this.config.cliArgs,{detox:this.config.frameworkConfig.originFramework==="detox"});if(n.length===0)return r;for(let{spec:s,message:c}of n)E("Discovery could not load %s: %s",s,zn(c));let o=$e(r,n,this.instances);return E("The tests of these files are listed from the results of the shard that ran them. Currents can show the run as finished before the other shards upload."),mr("Files that did not run on this shard: %o",o),r.filter(s=>s.tests.length>0)}};function zn(t){return t.split(`
|
|
10
|
-
`).map(e=>e.trim()).find(e=>e&&!e.startsWith("\u25CF"))??""}var
|
|
9
|
+
`]:["Unexpected network error"]}var he=c.extend("http");async function v(t,e,r=et){try{let n=await r(t).request(e);return he("network response: %o",{...Ae.default.omit(n,"request","config"),url:n.config.url,method:n.config.method}),n}catch(n){let o=n;throw he("network error: %o",{code:o.code,message:o.message,url:o.config?.url,method:o.config?.method,status:o.response?.status,headers:o.response?.headers,data:o.response?.data}),Ce(o),o}}var _i=c.extend("api");var Oi=c.extend("api");var De=require("util"),Se=require("zlib");var Ue=c.extend("api"),Sn=(0,De.promisify)(Se.gzip);async function Oe(t){try{Ue("Run params: %o",N(t));let e=await On(JSON.stringify(t));return v("api",{url:"v1/runs",method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":"gzip"},data:e}).then(r=>r.data)}catch(e){throw Ue("Failed to create the run:",e),e}}async function On(t){try{return await Sn(t)}catch(e){throw R("Failed to compress run payload:",e),e}}var ji=c.extend("api");var yn=c.extend("api");async function Ne(t,e){try{return await v("api",{url:`rules/project/${encodeURIComponent(t)}`,method:"GET",headers:{"x-currents-key":e}}).then(r=>r.data.rules)}catch(r){throw yn("Failed to get the project actions:",r),r}}var Nn=require("axios");var sa=c.extend("api");var Nt={apiKey:{name:"API key",env:"CURRENTS_API_KEY",cli:"--api-key"},recordKey:{name:"Record key",env:"CURRENTS_RECORD_KEY",cli:"--key"},projectId:{name:"Project ID",env:"CURRENTS_PROJECT_ID",cli:"--project-id"},ciBuildId:{name:"CI build ID",env:"CURRENTS_CI_BUILD_ID",cli:"--ci-build-id"},machineId:{name:"Machine ID",env:"CURRENTS_MACHINE_ID",cli:"--machine-id"},tag:{name:"Tag",cli:"--tag"},debug:{name:"Debug",env:"CURRENTS_DEBUG",cli:"--debug"}};var{debug:xn,ciBuildId:Ln,recordKey:Pn,projectId:Bn,machineId:wn}=Nt,bn={debug:xn,ciBuildId:Ln,recordKey:Pn,projectId:Bn,machineId:wn,tag:{...Nt.tag,env:"CURRENTS_TAG"},disableTitleTags:{name:"Disable title tags",env:"CURRENTS_DISABLE_TITLE_TAGS",cli:"--disable-title-tags"},removeTitleTags:{name:"Remove title tags",env:"CURRENTS_REMOVE_TITLE_TAGS",cli:"--remove-title-tags"},environment:{name:"Environment",env:"CURRENTS_ENVIRONMENT",cli:"--environment"},failOnFailures:{name:"Fail on failures",env:"CURRENTS_FAIL_ON_FAILURES",cli:"--fail-on-failures"},reportDir:{name:"Report folder",env:"CURRENTS_REPORT_DIR",cli:"--report-dir"}};var Ba=c.extend("config");var Mn=null;function xe(){return Mn}var C=require("@currents/rules");var rt=c.extend("actions"),vn=512;async function Be(t,e){try{let r=await Ne(t,e);if(!Array.isArray(r))throw new Error("The project actions are not a list");return rt("Fetched %d project actions",r.length),r}catch(r){return d("Failed to fetch the project actions, uploading without them"),rt("Failed to fetch the project actions: %o",r),[]}}function we({actions:t,instances:e,fullTestSuite:r,gitInfo:n,runTags:o,disableTitleTags:s=!1,group:a}){let p={skipped:0,quarantined:0,tagged:0};if(t.length===0)return p;let m=new C.RulesEvalBase(t,rt);for(let u of e){let f=a??u.groupId;for(let E of u.results.tests){let I=s?[]:Fe(r,{groupId:f,spec:u.spec,testId:E.testId})?.test.tags??[],h=m.getMatchedRules(Fn({groupId:f,spec:u.spec,test:E,gitInfo:n,tags:[...I,...o]}));if(h.length===0)continue;rt("Test %s matched actions: %j",E.testId,h);let S=Gn(E,h);S.length>0&&(kn(r,{groupId:f,spec:u.spec,testId:E.testId,tags:S}),p.tagged++);let K=Le(h,C.ACTION_TYPE.SKIP),Y=Le(h,C.ACTION_TYPE.QUARANTINE);K?(Pe(E,K,C.ACTION_ANNOTATIONS.SKIP_POST),p.skipped++):Y&&E.state==="failed"&&(Pe(E,Y,C.ACTION_ANNOTATIONS.QUARANTINE_POST),p.quarantined++)}}return p}function be(t){t.skipped+t.quarantined+t.tagged!==0&&G("[currents] Actions: %d tests skipped, %d quarantined, %d tagged",t.skipped,t.quarantined,t.tagged)}function Fn({groupId:t,spec:e,test:r,gitInfo:n,tags:o}){return{title:r.title[r.title.length-1],titlePath:[e,...r.title],file:e,project:t,testId:r.testId,tag:Array.from(new Set([...r.tags??[],...o])),gitInfo:n&&{branch:n.branch,authorName:n.authorName,authorEmail:n.authorEmail,remoteOrigin:n.remoteOrigin,message:n.message},errors:r.attempts.flatMap(s=>s.errors).filter(s=>!!s.message).map(s=>({message:s.message}))}}function Le(t,e){return t.find(r=>r.action.some(n=>n.op===e))}function Gn(t,e){let r=[];for(let n of e)for(let o of n.action){if(o.op!==C.ACTION_TYPE.TAG)continue;let s=(0,C.normalizeTagMatcherValue)(o.details?.tags??[]);s.length!==0&&(Me(t,C.ACTION_ANNOTATIONS.TAG,ve({action:n,type:C.ACTION_TYPE.TAG,testId:t.testId,extraDetails:{tags:s}})),r.push(...(0,C.normalizeTagMatcherValue)(s,{removeAtPrefix:!0})))}return r.length>0&&(t.tags=Array.from(new Set([...t.tags??[],...r]))),r}function Pe(t,e,r){let n=t.state;Me(t,r,ve({action:e,type:r===C.ACTION_ANNOTATIONS.SKIP_POST?C.ACTION_TYPE.SKIP:C.ACTION_TYPE.QUARANTINE,testId:t.testId,extraDetails:{status:n}})),t.state="pending"}function Me(t,e,r){t.annotations=[...t.annotations??[],{type:e,description:JSON.stringify(r),source:"test"}]}function ve({action:t,type:e,testId:r,extraDetails:n}){return{rule:{v:t.v,id:t._id,name:t.name.slice(0,vn),type:e,extraDetails:n,appliedAt:Date.now()},testInfo:{testId:r,status:n.status}}}function Fe(t,{groupId:e,spec:r,testId:n}){let o=t.find(a=>a.name===e),s=o?.tests.find(a=>a.spec===r&&a.testId===n);return o&&s?{project:o,test:s}:null}function kn(t,{groupId:e,spec:r,testId:n,tags:o}){let s=Fe(t,{groupId:e,spec:r,testId:n});if(!s)return;let{project:a,test:p}=s;p.tags=Array.from(new Set([...p.tags,...o])),a.tags=Array.from(new Set([...a.tags,...o]))}var Lt=l(require("fs-extra")),L=require("path");var jn=l(require("path")),Ge={".png":{type:"screenshot",contentType:"image/png"},".jpg":{type:"screenshot",contentType:"image/jpeg"},".jpeg":{type:"screenshot",contentType:"image/jpeg"},".webp":{type:"screenshot",contentType:"image/webp"},".gif":{type:"screenshot",contentType:"image/gif"},".mp4":{type:"video",contentType:"video/mp4"},".webm":{type:"video",contentType:"video/webm"},".svg":{type:"attachment",contentType:"image/svg+xml"},".log":{type:"attachment",contentType:"text/plain"},".txt":{type:"attachment",contentType:"text/plain"},".yml":{type:"attachment",contentType:"text/plain"},".yaml":{type:"attachment",contentType:"text/plain"},".md":{type:"attachment",contentType:"text/markdown"},".html":{type:"attachment",contentType:"text/html"},".csv":{type:"attachment",contentType:"text/csv"},".json":{type:"attachment",contentType:"application/json"},".pdf":{type:"attachment",contentType:"application/pdf"},".gz":{type:"attachment",contentType:"application/gzip"},".viewhierarchy":{type:"attachment",contentType:"application/xml"}};var ke=l(require("fs-extra")),je=require("path"),xt=c.extend("detox"),Hn="detox.json";function He(t){return[...t].sort((e,r)=>(e.session??0)-(r.session??0)||e.invocations-r.invocations)}async function Ke(t){let e=(0,je.join)(t,Hn);try{let r=await ke.default.readJson(e);if(typeof r?.artifactsRootDir!="string"||!Array.isArray(r?.tests)){xt("Unexpected Detox manifest contents at %s",e);return}return xt("Detox manifest: %o",r),r}catch{xt("No Detox manifest at %s",e);return}}var nt=require("path"),Kn=c.extend("detox"),Je=255,Jn=/[/\\?<>:*|"$\u0000-\u001f]/g,Ye=4;function $e(t){return Yn(t)??$n(t)}function Yn({rootDir:t,fullName:e,status:r,invocations:n}){try{let o=require.resolve("detox/src/artifacts/utils/ArtifactPathBuilder",{paths:[process.cwd()]}),s=require(o),a=new s({rootDir:t});return(0,nt.dirname)(a.buildPathForTestArtifact("test.mp4",{fullName:e,status:r,invocations:n}))}catch(o){Kn("Detox path builder is not available: %o",o);return}}function $n({rootDir:t,fullName:e,status:r,invocations:n}){let o=Wn(r),s=n>1?` (${n})`:"",a=e.slice(-Je+o.length+s.length),p=`${o}${a}${s}`.replace(Jn,"_");return(0,nt.join)(t,Vn(p,Je))}function Vn(t,e){let r=Buffer.from(t,"utf8");return r.length<=e?t:r.subarray(0,e).toString("utf8").replace(/\uFFFD$/,"")}function Wn(t){switch(t){case"passed":return"\u2713 ";case"failed":return"\u2717 ";default:return""}}var We=l(require("fs-extra")),qe=require("path"),Ve=c.extend("detox"),ot="detox.trace.json",qn="ws-client-invocation";async function Qe(t){let e=(0,qe.join)(t,ot),r=new Map,n;try{n=await We.default.readJson(e)}catch{return Ve("No Detox trace at %s",e),r}if(!Array.isArray(n))return Ve("Unexpected Detox trace contents at %s",e),r;let o=Qn(n);return zn(n).forEach(({pid:a,ts:p,step:m})=>{o.filter(f=>f.pid===a&&p>=f.startTs&&p<=f.endTs).sort((f,E)=>f.startTs-E.startTs).pop()?.steps.push(m)}),o.forEach(({fullName:a,invocations:p,steps:m})=>{let u=r.get(a)??[];u.push({fullName:a,invocations:p,steps:m.sort((f,E)=>+new Date(f.startTime)-+new Date(E.startTime))}),r.set(a,u)}),r}function Qn(t){let e=new Map,r=[];t.forEach(o=>{let s=`${o.pid}:${o.tid}`,a=e.get(s)??[];if(e.set(s,a),o.ph==="B"){a.push(Xn(o));return}if(o.ph==="E"){let p=a.pop();p&&r.push({...p,endTs:Number(o.ts)})}});let n=[...e.values()].flatMap(o=>o.filter(s=>s!==void 0));return[...r,...n]}function Xn(t){let e=t.args?.fullName;if(!(t.args?.context!=="test"||typeof e!="string"))return{fullName:e,invocations:Number(t.args?.invocations??1),pid:Number(t.pid),startTs:Number(t.ts),endTs:Number.MAX_SAFE_INTEGER,steps:[]}}function zn(t){let e=new Map,r=[];return t.forEach(n=>{if(!n.cat?.includes(qn))return;let o=`${n.pid}:${n.tid}`,s=e.get(o)??[];if(n.ph==="B"){s.push({name:n.name??"action",cat:n.cat,ts:Number(n.ts)}),e.set(o,s);return}if(n.ph==="E"){let a=s.pop();if(!a)return;r.push({pid:Number(n.pid),ts:a.ts,step:{title:a.name,category:"detox",startTime:new Date(a.ts/1e3).toISOString(),duration:Math.round((Number(n.ts)-a.ts)/1e3),steps:[]}})}}),r}var J=c.extend("detox"),Xe="artifacts",Zn=[".mp4",".png",".jpg",".log",".txt",".json",".viewhierarchy"],to=t=>{let e=(0,L.extname)(t);return Zn.includes(e)?Ge[e]:void 0};async function ze({instances:t,reportDir:e,manifest:r}){let n=ro(r),o=await Qe(r.artifactsRootDir),s=await re((0,L.join)(e,Xe)),a={artifacts:0,steps:0};for(let p of t)for(let m of p.results.tests){let u=n.get(m.testId);if(!u){J("No Detox manifest entry for %s",m.testId);continue}await no({test:m,manifestTest:u,rootDir:r.artifactsRootDir,artifactsDir:s,traceSlices:o.get(u.fullName)??[],result:a})}return a.artifacts+=await eo({instances:t,rootDir:r.artifactsRootDir,artifactsDir:s}),a}async function eo({instances:t,rootDir:e,artifactsDir:r}){if(!await Lt.default.pathExists((0,L.join)(e,ot)))return 0;let[n]=await Ze(e,[ot],r),o=t.map(s=>s.results.tests[0]).filter(s=>s!==void 0);return o.forEach(s=>{s.artifacts=[...s.artifacts??[],n]}),o.length}function ro(t){let e=new Map;return t.tests.forEach(r=>{e.set(r.fullName,[...e.get(r.fullName)??[],r.testId])}),new Map(t.tests.filter(r=>{let n=e.get(r.fullName)?.length===1;return n||J("Ambiguous Detox test name, skipping: %s",r.fullName),n}).map(r=>[r.testId,r]))}async function no({test:t,manifestTest:e,rootDir:r,artifactsDir:n,traceSlices:o,result:s}){let a=[...t.attempts].sort((u,f)=>u.attempt-f.attempt),p=He(e.attempts),m=1;for(let[u,f]of p.entries()){let E=a[u];if(!E){J("No reported attempt %d of %s",u,e.fullName);continue}let I=await oo({fullName:e.fullName,status:f.status,rootDir:r,artifactsDir:n,fromInvocation:m});I&&(m=I.invocation+1,E.artifacts=[...E.artifacts??[],...I.artifacts],s.artifacts+=I.artifacts.length);let h=io(o,u,I?.invocation);h.length&&(E.steps=[...E.steps??[],...h],s.steps+=h.length)}}async function oo({fullName:t,status:e,rootDir:r,artifactsDir:n,fromInvocation:o}){for(let s=o;s<o+Ye;s++){let a=$e({rootDir:r,fullName:t,status:e,invocations:s}),p=await so(a);if(p)return{invocation:s,artifacts:await Ze(a,p,n)}}J("No Detox artifacts for %s [%s]",t,e)}async function so(t){try{return(await Lt.default.readdir(t)).sort()}catch{return}}async function Ze(t,e,r){let n=[];for(let o of e){let s=to(o);if(!s){J("Skipping unsupported Detox artifact %s",o);continue}let a=(0,L.join)(t,o),p=`${se(a)}${(0,L.extname)(o)}`;await ne(a,(0,L.join)(r,p)),n.push({...s,path:(0,L.join)(Xe,p),name:o})}return n}function io(t,e,r){return((r===void 0?void 0:t.find(s=>s.invocations===r))??[...t].sort((s,a)=>s.invocations-a.invocations)[e])?.steps??[]}var B=class{constructor(e){this.config=e}async getFullTestSuite(){return[]}};var co=l(require("crypto"));var tr=l(require("fs-extra")),ao=l(require("path"));async function st(t){let e=await tr.default.pathExists(t);if(!e)throw new Error("File does not exist");return e}function er(){return"root"}function rr(t){let e=(t.join(" ").match(/@(\S+)/g)??[]).filter(Boolean).map(r=>r);return Array.from(new Set([...e].map(r=>r.trim()).map(r=>r.replace("@",""))))}var po=/^[0-9a-f]{32}$/;function nr(t){let e=[];for(let r of t){let n=e.find(o=>o.name===r.groupId);n||(n={name:r.groupId,tags:[],tests:[]},e.push(n)),n.tests.push(...sr(r))}return e.length===1&&po.test(e[0].name)&&(e[0].name=er()),e}function or(t,e,r){let n=[];for(let{projectId:o,spec:s}of e){let a=r.find(m=>m.spec===s&&m.groupId===o)??(t.length===1?r.find(m=>m.spec===s):void 0);if(!a){n.push(s);continue}let p=t.length===1?t[0]:t.find(m=>m.name===o);p||(p={name:o,tags:[],tests:[]},t.push(p)),p.tests.push(...sr(a))}return n}function sr(t){return t.results.tests.map(e=>({spec:t.spec,testId:e.testId,title:e.title,tags:e.tags??rr(e.title)}))}var _r=l(require("fs-extra")),Cr=l(require("tmp"));var Tr=require("lodash");function ir(t){let e=[];for(let[r,n]of Object.entries(t))r==="_"||r==="$0"||r.includes("-")||(typeof n=="boolean"?n&&e.push(`--${r}`):Array.isArray(n)?n.forEach(o=>{e.push(`--${r}=${o}`)}):e.push(`--${r}=${n}`));return e.join(" ")}var ar=require("lodash"),uo=["bail","clearCache","collectCoverage","collectCoverageFrom","color","colors","config","coverage","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","debug","detectLeaks","detectOpenHandles","errorOnDeprecated","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","notify","notifyMode","openHandlesTimeout","outputFile","reporters","runner","shard","showConfig","showSeed","silent","testFailureExitCode","testNamePattern","verbose","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll","watchPathIgnorePatterns","watchman"];function cr(t){return(0,ar.omit)(t,...uo)}var gr=l(require("fs")),pt=require("lodash"),Bt=l(require("path"));var Pt=l(require("fs")),it=require("module"),at=l(require("path")),pr=l(require("semver")),lo=">=29.5.0";function mo(){let t=(0,it.createRequire)(at.default.join(process.cwd(),"package.json"));if(fo(t)==="jest-cli")return t.resolve("jest-cli");try{return(0,it.createRequire)(t.resolve("jest")).resolve("jest-cli")}catch{}try{return t.resolve("jest-cli")}catch{throw new Error(`Jest discovery needs the "jest" package, and it is not installed in ${process.cwd()}. Run the command from the folder of the project that ran the tests, or install Jest 29.5 or later: npm install --save-dev jest`)}}function fo(t){for(let e of t.resolve.paths("jest")??[]){if(Pt.default.existsSync(at.default.join(e,"jest","package.json")))return"jest";if(Pt.default.existsSync(at.default.join(e,"jest-cli","package.json")))return"jest-cli"}return null}function ur(){let t=(0,it.createRequire)(mo()),{version:e}=t("jest-cli/package.json");if(!pr.default.satisfies(e,lo,{includePrerelease:!0}))throw new Error(`Jest discovery needs Jest 29.5 or later, and ${process.cwd()} has Jest ${e}. Update Jest: npm install --save-dev jest@latest`);return t}function lr(){return ur()("jest-cli")}function mr(){return ur()("jest-config")}function ct(t,e){return(...r)=>new Promise((n,o)=>{let s=0,a=()=>{s++;try{let p=t(...r);n(p)}catch(p){if(s>=e.length)o(p);else{let m=e[s-1];setTimeout(a,m)}}};a()})}var fr=c.extend("jest-discovery");function dr(t){return["testEnvironment","globalSetup","globalTeardown"].some(e=>String(t[e]??"").includes("detox"))}function Er(t){return{...(0,pt.omit)(t,["globalSetup","globalTeardown","testEnvironmentOptions"]),testEnvironment:"node"}}async function Ir(t,e){let r=e.detox;try{let{readInitialOptions:n}=mr(),{config:o,configPath:s}=await n(t);r||=[o,...o.projects??[]].some(I=>typeof I!="string"&&dr(I));let a=["collectCoverage","collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","coverageProvider","coverageReporters","coverageThreshold","errorOnDeprecated","forceCoverageMatch","notify","notifyMode","openHandlesTimeout","reporters","runner","showSeed","testFailureExitCode","verbose","watchPathIgnorePatterns","watchPlugins","watchman","bail","clearCache","color","colors","debug","detectLeaks","detectOpenHandles","expand","forceExit","json","listTests","logHeapUsage","noStackTrace","outputFile","shard","showConfig","silent","testNamePattern","waitNextEventLoopTurnForUnhandledRejectionEvents","watch","watchAll"],p=["collectCoverageFrom","coverageDirectory","coveragePathIgnorePatterns","detectLeaks","detectOpenHandles","errorOnDeprecated","forceCoverageMatch","openHandlesTimeout","runner","watchPathIgnorePatterns"],m=I=>e.detox||dr(I),u=(0,pt.omit)(o,a);if(m(u)&&(u=Er(u)),u.projects&&(u.projects=u.projects.map(I=>{if(typeof I=="string")return I;let h=(0,pt.omit)(I,p);return m(h)?Er(h):h})),u.rootDir&&Object.keys(u).length===1)return null;let f=Bt.default.resolve(s?Bt.default.dirname(s):process.cwd(),`.jest-scanner-${new Date().getTime()}.config.cjs`),E=`module.exports=${JSON.stringify(u,null,2)}`;return fr("configFileContent: %O",E),gr.default.writeFileSync(f,E),await ct(st,[200,200,200,200,200,1e3])(f),f}catch(n){if(fr("error %o",n),r)throw new Error(`Failed to recreate the Jest config for discovery: ${n.message}`);return R("Failed to recreate the config file"),null}}async function Rr(t,e){let r="!!##ThisPatternWillNotMatchAnyTestName##!!",n=t.options,o=cr(n),s=ir(o),a=n.config,p=await Ir(a,e);return{cliArgs:[s,"--testNamePattern",r,"--reporters",require.resolve("@currents/cmd/discovery/jest"),"--shard=1/1","--testFailureExitCode=0",p?`--config=${p}`:"",...t.args].filter(u=>!(0,Tr.isEmpty)(u)),configFilePath:p}}var Eo=c.extend("jest-discovery");async function hr(t,e){console.time(k("@currents/jest:fullTestSuite-ready"));let{run:r}=lr(),{cliArgs:n,configFilePath:o}=await Rr(t,e);try{let s=Cr.default.fileSync({postfix:".json"});return Eo("running scanner: %o",n),process.env.CURRENTS_DISCOVERY_PATH=s.name,await r(n.concat(["--openHandlesTimeout=0"])),await ct(st,Array.from({length:300},()=>100))(s.name),console.timeEnd(k("@currents/jest:fullTestSuite-ready")),await M(s.name)}catch(s){return R("Failed to obtain the jest full test suite:",s),{fullTestSuite:[],specsWithoutResults:[]}}finally{o&&_r.default.unlinkSync(o)}}var Ar=c.extend("jest-discovery"),ut=class extends B{constructor(r,n){super(r);this.instances=n}async getFullTestSuite(){if(!this.config.frameworkConfig?.shard)return Ar("Not a sharded run, listing the tests of the results"),nr(this.instances);let{fullTestSuite:r,specsWithoutResults:n}=await hr(this.config.cliArgs,{detox:this.config.frameworkConfig.originFramework==="detox"});if(n.length===0)return r;for(let{spec:s,message:a}of n)d("Discovery could not load %s: %s",s,go(a));let o=or(r,n,this.instances);return d("The tests of these files are listed from the results of the shard that ran them. Currents can show the run as finished before the other shards upload."),Ar("Files that did not run on this shard: %o",o),r.filter(s=>s.tests.length>0)}};function go(t){return t.split(`
|
|
10
|
+
`).map(e=>e.trim()).find(e=>e&&!e.startsWith("\u25CF"))??""}var Dr=l(require("fs-extra"));var Ur=l(require("path"));function lt(t){return Ur.default.join(t,"fullTestSuite.json")}var Io=c.extend("junit-discovery");async function Sr(t){console.time(k("@currents/junit:fullTestSuite-ready"));try{Io("running scanner: %o",t);let e=lt(t);process.env.CURRENTS_DISCOVERY_PATH=e;let r=Dr.default.readFileSync(e,"utf-8");return JSON.parse(r)}catch(e){return R("Failed to obtain the junit full test suite:",e),[]}}var mt=class extends B{constructor(e,r){super(e),this.reportDir=r}async getFullTestSuite(){return Sr(this.reportDir)}};function Or(t,e,r){switch(t.framework){case"jest":return new ut(t,r);case"junit":return new mt(t,e);default:return new B(t)}}var w=l(require("fs-extra")),P=l(require("path"));async function yr(t){let e=await To(t?.reportDir);return{reportDir:e,configFilePath:t?.configFilePath??P.default.join(e,"config.json")}}async function To(t){if(t){if(!await w.default.pathExists(t))throw new Error(`No reports found: the folder "${t}" does not exist.`);return t}let e=(0,P.join)(process.cwd(),".currents"),r=await w.default.pathExists(e)?await Ro(e):null;if(!r)throw new Error(`No reports found: there is no report folder in "${e}". Run the tests with a Currents reporter first, or pass --report-dir with the folder of the reports.`);return r}async function Ro(t){let e=await w.default.readdir(t),r=null;for(let n of e){let o=P.default.join(t,n),s=await w.default.stat(o);s.isDirectory()&&(!r||s.birthtime>r.birthtime)&&(r={name:n,birthtime:s.birthtime})}return r?(0,P.resolve)(t,r.name):null}async function wt(t){try{return await w.default.pathExists(t)}catch{return R("Error checking if path exists:",R),!1}}async function Nr(t){let e=P.default.join(t,"instances");return _o(e)}async function _o(t){let e=await w.default.readdir(t),r=[];for(let n of e){let o=P.default.join(t,n);(await w.default.stat(o)).isFile()&&r.push(o)}return r}var Co=t=>Buffer.byteLength(JSON.stringify(t),"utf8"),xr=(t,e=1048576)=>{let r=[],n=[],o=0;for(let s of t){let a=Co(s);o+a>e&&(r.push(n),n=[],o=0),n.push(s),o+=a}return n.length>0&&r.push(n),r};var ho=3e4;async function wr(){let t=xe();if(!t)throw new Error("Currents config is missing!");let e=await yr(t);Gt(So(e.reportDir)),c("Reporter options: %o",e),G("Report directory: %s",e.reportDir);let r=await M(e.configFilePath);c("Report config: %o",r);let n=await Nr(e.reportDir);c("Found %d instance results in the reportDir: %s",n.length,e.reportDir);let o=Do(e.reportDir),s=await wt(o),a=lt(e.reportDir),p=null;if(s){let T=await M(o);d("Marker file detected. The report was already uploaded: %o",{runUrl:T.response.runUrl,isoDate:T.isoDate})}let m=[];for(let T of n)m.push(await M(T));if(p=await Oo(a),p)c("Full test suite file detected: %s",a);else{let x=await Or(r,e.reportDir,m).getFullTestSuite();if(!br(x)||Mr(x))throw new Error("Failed to discover the full test suite!");p=x,await ht(a,JSON.stringify(p))}t.environment&&(p=p.map(T=>({...T,environment:T.environment??t.environment})));let u=p.length===1?p[0].name:null,f={currents:t},E={type:r.framework,version:r.frameworkVersion,clientVersion:Q,frameworkConfig:{originFramework:r.frameworkConfig?.originFramework,originFrameworkVersion:r.frameworkConfig?.originFrameworkVersion}},I=W.userFacingNanoid(),h=Jt(t.ciBuildId),S={};for(let T of m)S[T.groupId]||(S[T.groupId]=[]),S[T.groupId].push(T);let K=await Ke(e.reportDir);if(K){let T=await ze({instances:Object.values(S).flat(),reportDir:e.reportDir,manifest:K});G("[currents] Attached %d Detox artifacts and %d steps",T.artifacts,T.steps)}let Y=await Be(t.projectId,t.recordKey);be(we({actions:Y,instances:Object.values(S).flat(),fullTestSuite:p,gitInfo:await Tt(),runTags:t.tag??[],disableTitleTags:t.disableTitleTags,group:u}));let $=new Map;Object.values(S).forEach(T=>{T.forEach(x=>{x.artifacts?.forEach(O=>{O&&$.set(O.path,O.contentType)}),x.results.tests.forEach(O=>{O.artifacts?.forEach(D=>{D&&$.set(D.path,D.contentType)}),O.attempts.forEach(D=>{D.artifacts?.forEach(b=>{b&&$.set(b.path,b.contentType)})})})})});for await(let T of Object.keys(S)){let x=S[T],O=T;u&&(c("Default group found: %s, overwriting the group in the results",u),O=u,x=x.map(D=>({...D,groupId:u})));try{let D=xr(x),b=await Lr({ci:h,group:O,instances:[],fullTestSuite:p,config:f,machineId:I,framework:E});for(let dt=0;dt<D.length;dt++){let Et=await Lr({ci:h,group:O,instances:D[dt],fullTestSuite:[],config:f,machineId:I,framework:E});Et.artifactUploadUrls&&Et.artifactUploadUrls.length>0&&await yo(Et.artifactUploadUrls,e.reportDir,$)}c("Api response: %o",b),G("[%s] Run created: %s",O,b.runUrl);let vr={response:b,isoDate:new Date().toISOString()};await ht(o,JSON.stringify(vr)),c("Marker file %s: %s",s?"overwritten":"created",o)}catch(D){throw c("Failed to upload the results to the dashboard"),D}}t.failOnFailures&&Uo(m)}var Ao=10;function Uo(t){let e=t.flatMap(o=>o.results.tests.filter(s=>s.state==="failed").map(s=>`${o.spec}: ${s.title.join(" > ")}`));if(e.length===0)return;let r=e.slice(0,Ao),n=e.length-r.length;throw new Error([`${e.length} ${e.length===1?"test":"tests"} failed (--fail-on-failures):`,...r.map(o=>` - ${o}`),...n>0?[` and ${n} more`]:[]].join(`
|
|
11
|
+
`))}async function Lr({ci:t,group:e,instances:r,fullTestSuite:n,config:o,machineId:s,framework:a}){let p=await Tt(),m=await Qt(),u={browserName:"node",browserVersion:Br.default.coerce(process.version)?.version},{currents:f}=o,I={platform:{...u,...m},ci:t,commit:p,group:e,fullTestSuite:n,config:o,projectId:f.projectId,recordKey:f.recordKey,ciBuildId:t.ciBuildId.value??void 0,tags:f.tag??[],machineId:f.machineId??s,framework:a,instances:r,previousCiBuildId:process.env.CURRENTS_PREVIOUS_CI_BUILD_ID};return c("Creating run: %o",N(I)),Oe(I)}function Do(t){return ft.default.join(t,"upload.marker.json")}function So(t){return ft.default.join(t,`.debug-${new Date().toISOString()}.log`)}async function Oo(t){if(!await wt(t))return null;try{let e=await M(t);return!br(e)||Mr(e)?(d("Ignoring %s, it is not a list of projects and tests",t),null):e}catch(e){return d("Ignoring %s, it is not valid JSON: %s",t,e),null}}function br(t){return Array.isArray(t)&&t.every(e=>typeof e?.name=="string"&&Array.isArray(e.tests)&&e.tests.every(r=>typeof r?.spec=="string"&&typeof r.testId=="string"&&Array.isArray(r.title)&&r.title.every(n=>typeof n=="string")))}function Mr(t){return t.length===0||t.some(e=>e.tests.length===0)}async function yo(t,e,r){c("Uploading %d artifacts",t.length),await Promise.all(t.map(n=>{let o=ft.default.join(e,n.path),s=r.get(n.path)||"application/octet-stream";return No(o,s,n.uploadUrl)}))}var No=async(t,e,r)=>{try{if(!await bt.default.pathExists(t)){d("Artifact file not found: %s",t);return}let n=await bt.default.readFile(t);await Pr.default.put(r,n,{headers:{"Content-Type":e},timeout:ho})}catch(n){c("Failed to upload artifact %s: %o",t,n)}};0&&(module.exports={handleCurrentsReport});
|
|
11
12
|
/*! For license information please see index.js.LEGAL.txt */
|
|
12
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,122 +5,40 @@ description: Run the Currents CLI (the `currents` command of the npm package @cu
|
|
|
5
5
|
|
|
6
6
|
# Currents CLI
|
|
7
7
|
|
|
8
|
-
`currents`
|
|
9
|
-
|
|
10
|
-
## Install
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install --save-dev @currents/cmd
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
In the project, run it as `npx currents`. Outside a project, use `npx --package @currents/cmd currents`: without the package installed, `npx currents` runs an unrelated npm package named `currents`.
|
|
8
|
+
`currents` is the command of the npm package `@currents/cmd`. In a project that has the package, run `npx currents`. Elsewhere, run `npx --package @currents/cmd currents`: `npx currents` alone runs an unrelated npm package.
|
|
17
9
|
|
|
18
10
|
## Pick the command
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
| Save the last run so that a CI rerun runs only the failed Playwright tests | `currents cache set` and `cache get` with `--preset last-run` |
|
|
28
|
-
| Save files in one CI job and restore them in another | `currents cache set` and `cache get` with `--id` |
|
|
29
|
-
| Get the data of a run | `currents run get` |
|
|
30
|
-
| Call any other REST API route, such as listing runs or cancelling a run | `currents api <path>` |
|
|
12
|
+
- `currents run upload`: upload the results of a Currents reporter (Jest, Node test runner, Detox). With `--input-format junit`, upload JUnit XML.
|
|
13
|
+
- `currents run attach`: attach logs or other files to a run that CI recorded.
|
|
14
|
+
- `currents run cancel`: cancel a run when its CI workflow is cancelled.
|
|
15
|
+
- `currents run get`: get the data of a run.
|
|
16
|
+
- `currents session start`, then `session attach` and `session share`: record a browser session and share a link to it.
|
|
17
|
+
- `currents cache set` and `cache get` with `--preset last-run`: rerun only the failed Playwright tests in a CI rerun. With `--id`: save files in one CI job and restore them in another.
|
|
18
|
+
- `currents api <path>`: call any other REST API route.
|
|
31
19
|
|
|
32
20
|
`@currents/playwright` and the Cypress integration send results themselves. Do not add `currents run upload` after them.
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Examples
|
|
37
|
-
|
|
38
|
-
These are the examples from `--help`:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
currents run upload --key <record-key> --project-id <id> --ci-build-id <build-id>
|
|
42
|
-
currents run upload --key <record-key> --project-id <id> --ci-build-id <build-id> --input-format junit --input-file "./*.xml" --framework postman
|
|
43
|
-
currents run attach --key <record-key> --project-id <id> --ci-build-id <build-id> --machine-id shard-1 docker-logs.zip
|
|
44
|
-
currents run attach --key <record-key> --project-id <id> --ci-build-id <build-id> --spec tests/cart.spec.ts --test-title "adds an item" --attempt 0 screenshot.png
|
|
45
|
-
currents run cancel --key <record-key> --project-id <id> --ci-build-id <build-id>
|
|
46
|
-
currents cache set --key <record-key> --preset last-run
|
|
47
|
-
currents cache get --key <record-key> --preset last-run
|
|
48
|
-
currents run get --api-key <api-key> --project-id <project-id> --ci-build-id <ci-build-id>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
- With `--input-format`, `run upload` converts the reports to the Currents format first, then uploads them. Put quotes around the `--input-file` pattern so that the CLI expands it, not the shell: the shell passes only the first file.
|
|
52
|
-
- Without `--id`, `cache set` and `cache get` use an ID made from the CI job. When they warn `No CI job detected`, pass the same `--id` to both.
|
|
53
|
-
- Without `--spec`, `run attach` attaches the files to the whole run. `--machine-id` names the CI machine the files come from; run-level files are listed by machine when it is set. `--spec`, `--test-title` and `--attempt` attach to a spec file, a test or one attempt of a test (the first attempt is `0`).
|
|
54
|
-
|
|
55
|
-
## Call the REST API
|
|
56
|
-
|
|
57
|
-
`currents api <path>` sends a request to any route of the Currents REST API with the API key and prints the response body. Use it when no other command does the task. The routes are in the REST API docs: https://docs.currents.dev/resources/api/api-resources
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
currents api /v1/runs/<run-id>
|
|
61
|
-
currents api /v1/projects/<project-id>/runs -X GET -f "branches[]=main" -f status=FAILED
|
|
62
|
-
currents api /v1/runs/<run-id>/cancel -X PUT
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
- The path can start with `/v1/`, `v1/` or the route name.
|
|
66
|
-
- `-f key=value` adds a field; `true`, `false`, `null` and numbers are sent as JSON values. `-F key=value` adds a field that is always a string.
|
|
67
|
-
- Without `-X`, fields make the request a POST with the fields in a JSON body. A GET sends them in the query string, so pass `-X GET` with fields.
|
|
68
|
-
- `--input <file>` sends the file as the body; the fields then go in the query string, whatever the method.
|
|
69
|
-
- A response that is not 2xx prints its body on stderr and exits with `1`.
|
|
22
|
+
Before you use a command, run `currents <command> --help` for its options and examples, and do not use an option it does not list. For CI steps run `currents docs ci-setup`, and for the session flow run `currents docs sessions`. If `docs` is an unknown command, update `@currents/cmd`.
|
|
70
23
|
|
|
71
24
|
## Credentials
|
|
72
25
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| ---------------------------------------------------- | --------------------------------------------------- | -------------------- | ----------------------------------------- |
|
|
77
|
-
| `run upload`, `run cancel`, `cache set`, `cache get` | record key | `--key` | `CURRENTS_RECORD_KEY` |
|
|
78
|
-
| `run attach` | record key, or an API key when no record key is set | `--key`, `--api-key` | `CURRENTS_RECORD_KEY`, `CURRENTS_API_KEY` |
|
|
79
|
-
| `session start`, `session attach`, `session share` | record key, or an API key when no record key is set | `--key`, `--api-key` | `CURRENTS_RECORD_KEY`, `CURRENTS_API_KEY` |
|
|
80
|
-
| `run get`, `api` | API key | `--api-key` | `CURRENTS_API_KEY` |
|
|
81
|
-
|
|
82
|
-
Other environment variables the commands read:
|
|
83
|
-
|
|
84
|
-
- `CURRENTS_PROJECT_ID`: `run upload`, `run attach`, `run cancel`, `session start`, `run get`
|
|
85
|
-
- `CURRENTS_CI_BUILD_ID`: `run upload`, `run attach`, `run cancel`, `run get`. `run get` ignores it when `--branch` or `--tag` is set
|
|
86
|
-
- `CURRENTS_RUN_ID`: `run cancel`
|
|
87
|
-
- `CURRENTS_MACHINE_ID`: `run upload`, `run attach`
|
|
88
|
-
- `CURRENTS_SESSION_ID`: `session attach`, `session share`
|
|
89
|
-
- `CURRENTS_REPORT_DIR`: `run upload`
|
|
90
|
-
- `CURRENTS_TAG`: `run upload`, comma-separated tags for the run
|
|
91
|
-
- `CURRENTS_REMOVE_TITLE_TAGS`, `CURRENTS_DISABLE_TITLE_TAGS`: `run upload`, same as `--remove-title-tags` and `--disable-title-tags`
|
|
92
|
-
- `CURRENTS_PREVIOUS_CI_BUILD_ID`: `run upload`, the CI build ID of the earlier attempt of this CI build, sent with the run
|
|
93
|
-
- `CURRENTS_OUTPUT`: `run get`, same as `--output`
|
|
94
|
-
- `CURRENTS_DEBUG`: all commands, same as `--debug`
|
|
95
|
-
- `CURRENTS_API_URL`: the Currents API address for `run upload`, `run cancel` and `cache`. `CURRENTS_REST_API_URL`: the REST API address for `run attach`, `run get`, `session` and `api`. Set them only to reach a server other than Currents, such as a local test server
|
|
96
|
-
|
|
97
|
-
An option on the command line wins over its environment variable, and the environment variable wins over the default. For a flag such as `CURRENTS_DEBUG`, `false`, `0`, `no` and `off` turn it off, and any other value turns it on.
|
|
98
|
-
|
|
99
|
-
Set keys as environment variables or CI secrets, not as options, so that they stay out of shell history and CI logs. In CI, set `CURRENTS_CI_BUILD_ID` once for the job, so that the reporter, `run attach` and `run cancel` find the same run. `run cancel` does not find the CI build ID by itself: it needs `--ci-build-id` or `--run-id`.
|
|
100
|
-
|
|
101
|
-
## Exit codes
|
|
102
|
-
|
|
103
|
-
- `0`: the command finished. It is also `0` when `run cancel` finds no run to cancel, when `cache get --continue` finds no cache, and when `cache set --continue` finds no files to save.
|
|
104
|
-
- `1`: anything else. For example a missing option, an option value the command does not take, an API error, or a file that could not be uploaded. `currents` without a command prints the help and exits with `1`.
|
|
105
|
-
|
|
106
|
-
Errors go to stderr, prefixed with `ERROR`. Other output goes to stdout, except for `run get` without `--output`, `session start --json` and `api`: they print only the response or JSON on stdout, and everything else on stderr.
|
|
107
|
-
|
|
108
|
-
When a command fails:
|
|
26
|
+
- Record key, in `CURRENTS_RECORD_KEY` or `--key`: `run upload`, `run cancel`, `cache`.
|
|
27
|
+
- API key, in `CURRENTS_API_KEY` or `--api-key`: `run get`, `api`.
|
|
28
|
+
- `run attach` and `session` take either key. The record key wins when both are set.
|
|
109
29
|
|
|
110
|
-
|
|
111
|
-
2. A 401 or 403 from the API usually means the wrong key: a record key where an API key is needed, an API key without write access, or a key of another organization.
|
|
112
|
-
3. Run the command again with `--debug` to see the requests and the resolved configuration. Keys are replaced with `*****` in it.
|
|
113
|
-
4. `run attach` and `session attach` print `Attached <file>` for each file that arrived and `Failed <file>` for each that did not. Attach only the failed files again.
|
|
114
|
-
5. Do not retry a failed command in a loop. Report the error and what you tried.
|
|
30
|
+
Both keys come from the Currents dashboard. Set them as environment variables or CI secrets, not as options.
|
|
115
31
|
|
|
116
32
|
## Safety
|
|
117
33
|
|
|
118
|
-
- Never print,
|
|
119
|
-
-
|
|
120
|
-
- Anyone with a
|
|
121
|
-
- `run attach` and `session attach` refuse
|
|
34
|
+
- Never print, log or commit a key, and do not put one in a command you show to the user. Write `<record-key>` or name the environment variable.
|
|
35
|
+
- Do not commit `.currents-session/`, which `session start` writes.
|
|
36
|
+
- Anyone with a share link can open what you attach. Attach only test data and files from development accounts.
|
|
37
|
+
- `run attach` and `session attach` refuse `.env` files and skip hidden files. Do not rename or copy files to get around this.
|
|
122
38
|
|
|
123
|
-
##
|
|
39
|
+
## Exit codes and errors
|
|
124
40
|
|
|
125
|
-
-
|
|
126
|
-
-
|
|
41
|
+
- `0` when the command finished, `1` otherwise. Errors go to stderr, prefixed with `ERROR`.
|
|
42
|
+
- A 401 or 403 usually means the wrong key: a record key where an API key is needed, an API key without write access, or a key of another organization.
|
|
43
|
+
- Run the command again with `--debug` to see the requests. Keys are hidden in it.
|
|
44
|
+
- Do not retry a failed command in a loop. Report the error and what you tried.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: GitHub Actions and GitLab CI steps: upload results, attach files, cancel a run, rerun only the failed Playwright tests
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# CI setup
|
|
2
6
|
|
|
3
7
|
Steps for GitHub Actions and GitLab CI. They assume `@currents/cmd` is in the project's `devDependencies`, so that `npx currents` runs it.
|
|
@@ -49,7 +53,14 @@ For JUnit XML, `run upload` converts the reports first:
|
|
|
49
53
|
run: npx currents run upload --input-format junit --input-file "reports/*.xml" --framework postman
|
|
50
54
|
```
|
|
51
55
|
|
|
52
|
-
`--framework` takes `postman`, `node`, `vitest` or `wdio`. See `currents run upload --help`.
|
|
56
|
+
`--framework` takes `cypress`, `postman`, `node`, `vitest` or `wdio`. For Cypress run results saved by `after:run`, use `--input-format cypress-json --input-file results.json` without `--framework`: it uploads every attempt, screenshot and video. See `currents run upload --help`.
|
|
57
|
+
|
|
58
|
+
To let Currents actions quarantine tests, let the test step pass and fail the job from the upload. `--fail-on-failures` exits with 1 when a test failed that no action quarantined or skipped:
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
- run: npx detox test || true
|
|
62
|
+
- run: npx currents run upload --fail-on-failures
|
|
63
|
+
```
|
|
53
64
|
|
|
54
65
|
### Attach files to the run
|
|
55
66
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Record an agent or browser session as evidence and share it: start, attach, share and what each prints
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Sessions
|
|
2
6
|
|
|
3
7
|
A session holds the files of an ad-hoc, one-off agent or browser session, such as screenshots, a Playwright MCP trace and logs, and gives a link to share them. Use it as evidence: a bug before and after a fix, or proof that something works.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@currents/cmd",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Currents Software Inc",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@commander-js/extra-typings": "^14.0.0",
|
|
57
57
|
"@currents/commit-info": "2.0.0",
|
|
58
|
+
"@currents/rules": "^0.1.0",
|
|
58
59
|
"archiver": "^7.0.1",
|
|
59
60
|
"async-retry": "^1.3.3",
|
|
60
61
|
"axios": "1.20.0",
|
|
@@ -88,6 +89,7 @@
|
|
|
88
89
|
},
|
|
89
90
|
"files": [
|
|
90
91
|
"dist",
|
|
92
|
+
"docs",
|
|
91
93
|
"!**/*.map",
|
|
92
94
|
"!**/*/*.map"
|
|
93
95
|
],
|