@skyramp/testbot-core 0.12.0-v3.15 → 0.12.0-v3.16

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.
Files changed (2) hide show
  1. package/dist/main.js +1 -1
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -713,7 +713,7 @@ ${ctt(s,{order:t.stages.map(o=>o.name),wallMinutes:q$(s)})}
713
713
  `)?`
714
714
  `:""}${i.join(`
715
715
  `)}
716
- `)}var Htr="https://testbot.skyramp.dev",ag={attemptId:"v3AttemptId",origin:"v3Origin",deadlineAt:"v3DeadlineAt",reportUploaded:"v3ReportUploaded",recipeUploaded:"v3RecipeUploaded",cause:"v3Cause"},$tr="skyramp-sources",ztr=3e4;function Gtr(t){let e=t.ACTIONS_ID_TOKEN_REQUEST_URL,r=t.ACTIONS_ID_TOKEN_REQUEST_TOKEN;return delete t.ACTIONS_ID_TOKEN_REQUEST_URL,delete t.ACTIONS_ID_TOKEN_REQUEST_TOKEN,async n=>{if(!e||!r)throw new Error("The job cannot request an OIDC token. Give it the `id-token: write` permission.");let s=new URL(e);s.searchParams.set("audience",n);let i=await fetch(s,{headers:{Authorization:`Bearer ${r}`,Accept:"application/json"},redirect:"error",signal:AbortSignal.timeout(ztr)});if(!i.ok)throw new Error(`GitHub refused the OIDC token request: ${i.status}`);let o=(await i.json().catch(()=>({}))).value;if(typeof o!="string"||!o)throw new Error("GitHub's OIDC token response carried no token");return Ct(o),o}}function jtr(t,e){return{origin:t,idToken:e,mask:r=>Ct(r),log:r=>ee(r)}}function Om(t){VI(ag.attemptId)&&!VI(ag.cause)&&In(ag.cause,t)}function ZT(){Om("setup_failed")}function qtt(){Om("timed_out")}var Wle={cancelled:"Skyramp cancelled this run",expired:"this attempt passed its deadline in Skyramp",ended:"Skyramp already ended this attempt"},Htt={cancelled:"cancelled",expired:"timed_out",ended:"agent_failed"};function $tt(t){return e=>Rtt(t.attempt,r=>{Om(Htt[r]),J(`Testbot V3: ${Wle[r]}; stopping the run, and uploading nothing.`),e("attempt-closed",Wle[r])})}async function ztt(t){let e=await Itt(t.attempt);return e?(Om(Htt[e]),J(`Testbot V3: ${Wle[e]}, so nothing is uploaded.`),!0):!1}function Gtt(t){return[...t.attempt.manifest.credentials.map(e=>process.env[e.name]??""),t.attempt.license?.runToken??"",...t.heldInputs??[]].filter(Boolean)}function jtt(t){return!t||t.includes("generate")?{}:{stages:["analyze","recommend"],planOnly:!0}}async function z$(t){t.cancelWatch?.stop();let e=await t.attempt.revokeTokens();for(let r of e)J(`Testbot V3: could not revoke a scoped GitHub token (${r}); it stays valid until it expires.`)}function Vtr(t){let e=["SIGINT","SIGTERM"],r=()=>{n(),z$({attempt:t})},n=()=>{for(let s of e)process.removeListener(s,r)};for(let s of e)process.on(s,r);return{stop:n}}async function Vtt(t){let e=Gtr(process.env),r=Ue("skyrampAppOrigin").trim()||Htr,n=await Ctt(t,process.env,jtr(r,e)),s=Vtr(n);In(ag.attemptId,n.attemptId),In(ag.origin,r),In(ag.deadlineAt,n.deadlineAt.toISOString()),ee(`Testbot V3: attempt ${n.attemptNumber} of Validation Run ${t}, deadline ${n.deadlineAt.toISOString()}`);try{return{...await Wtr(n),cancelWatch:s}}catch(i){throw await z$({attempt:n,cancelWatch:s}),i}}async function Wtr(t){let e=Ftt(t.manifest,process.env);if(e.length>0)throw Om("credential_missing"),new Error(`The workflow does not supply the required credential${e.length>1?"s":""} ${e.join(", ")}. Add ${e.length>1?"them":"it"} to the Testbot step's env.`);let r;try{r=await vtt(t,{workspace:DS.join(process.env.GITHUB_WORKSPACE||process.cwd(),$tr)})}catch(o){throw ZT(),o}for(let o of r)ee(`Testbot V3: ${o.slug} at ${o.revision}`);await Ytr({attempt:t,sources:r});let n=Ptt(r);ee(`Testbot V3: working checkout ${n.repositorySlug}`);let s=Ttt(t.manifest,r);s&&ee(`Testbot V3: the pull request is ${s.repository}#${s.number}`);let i=await Btt(t);for(let o of i)ee([`Testbot V3: Change Set ${o.repository}#${o.number}`,o.note].filter(Boolean).join(": "));return{attempt:t,sources:r,layout:n,pullRequests:i,pullRequest:s}}async function Ytr(t){for(let e of t.sources)jle(e.path);Yle(t)||await Jtr(t)}async function Jtr(t){let e=t.sources[0],r;try{r=await Qtt(t.attempt)}catch(n){if(!(n instanceof UE&&n.status===404))throw ZT(),n;J(`Testbot V3: this Skyramp app does not serve the stored SUT recipe (${n.message}); deploy uses a source's own recipe, if one has it.`);return}if(!r){ee("Testbot V3: no stored SUT recipe for this Target yet; deploy uses a source's own recipe, if one has it.");return}Utt(e.path,r.files),ee(`Testbot V3: SUT recipe version ${r.version}, ${r.files.length} files, for ${e.slug} (uncommitted)`)}function Wtt(t){try{let e=JSON.parse(QS.readFileSync(DS.join(t,"@skyramp","mcp","package.json"),"utf-8")).version;return typeof e=="string"&&/^[0-9A-Za-z.+-]{1,64}$/.test(e)?e:"unknown"}catch{return"unknown"}}async function Ytt(t,e,r){e.aborted?Om("cancelled"):e.timedOut&&Om("timed_out");let n=e.outputsDir?DS.join(e.outputsDir,"report.json"):void 0;if(!n||!QS.existsSync(n)){J("Testbot V3: the run wrote no report, so Skyramp records it as an infrastructure error.");return}if(!await ztt(t))try{let s=JSON.parse(QS.readFileSync(n,"utf-8"));await _tt(t.attempt,{report:s,sources:t.sources,workingSlug:t.layout.repositorySlug,delivery:Ltt(e.outputsDir,t.sources,s,t.layout.repositorySlug),producer:{testbot:nH().version,mcp:Wtt(r)},secrets:Gtt(t)}),In(ag.reportUploaded,"true"),ee("Testbot V3: report uploaded; Skyramp derives the outcome.")}catch(s){J(`Testbot V3: the report upload failed: ${s instanceof Error?s.message:String(s)}`)}}function Yle(t){return t.attempt.manifest.trigger.kind==="sut_setup"}async function Jtt(t){let{capture:e}=await Dtt(t.attempt);return ile(e.settings.target.environment,"the run's SUT / Environment settings")}var Ktr={onboard:"onboard",deploy:"deploy"};function Ktt(t){return({stage:e,event:r,status:n})=>{let s=Ktr[e];if(!s)return;let i=r==="finished",o=n==="aborted"?"skipped":n;Mtt(t.attempt,{schemaVersion:1,stage:s,event:i?"finished":"started",...i&&o?{status:o}:{}}).catch(a=>J(`Testbot V3: could not report ${e} ${r}: ${a instanceof Error?a.message:String(a)}`))}}var Vle=t=>{try{return JSON.parse(QS.readFileSync(t,"utf-8"))}catch{return}};async function Xtt(t,e,r){e.aborted?Om("cancelled"):e.timedOut&&Om("timed_out");let n=e.outputsDir?Vle(DS.join(e.outputsDir,"onboard.json")):void 0;if(!n){J("Testbot V3: onboard wrote no answer, so there is no SUT recipe to send; Skyramp records the run as an infrastructure error.");return}if(await ztt(t))return;let s=Vle(DS.join(e.outputsDir,"deploy.json")),o=(e.stateFilePath?Vle(e.stateFilePath):void 0)?.stages.deploy?.attempts?.reduce((a,c)=>a+(c.totalMs??c.durationMs??0),0);try{let a=sZe(n,s,{deployDurationSeconds:o?Math.round(o/1e3):void 0,recipeFiles:s?ole(t.layout.repositoryPath):void 0});await Ott(t.attempt,{recipe:a,sources:t.sources,producer:{testbot:nH().version,mcp:Wtt(r)},secrets:Gtt(t)}),In(ag.recipeUploaded,"true"),ee(`Testbot V3: SUT recipe uploaded (${a.status}); Skyramp derives the outcome.`)}catch(a){J(`Testbot V3: the SUT recipe upload failed: ${a instanceof Error?a.message:String(a)}`)}}function Xtr(t){let e=t.split(/[\n,]/).map(r=>r.trim()).filter(Boolean);return e.length?e:void 0}function Ztr(t){if((t("testRepoPath")??"").trim())return"testRepoPath is not supported by the staged pipeline (pipeline: staged) \u2014 it writes tests into the application checkout only, and the Action's token has no write access to another repository. Use pipeline: classic for cross-repository delivery, or remove the input."}async function err(t,e,r,n=process.env.GITHUB_WORKSPACE||process.cwd()){let s=(t("relatedRepoPaths")??"").trim();if(!s)return[];let i=[];for(let o of s.split(/[\n,]/).map(a=>a.trim()).filter(Boolean)){let a=cg.resolve(n,o);if(!yo(n,o)){r(`relatedRepoPaths: ${o} is outside the workspace \u2014 skipping`);continue}if(!MS.existsSync(a)){r(`relatedRepoPaths: no checkout at ${o} \u2014 skipping`);continue}let c=await e(a);if(!c){r(`relatedRepoPaths: could not resolve owner/repo for ${o} (no origin remote?) \u2014 skipping`);continue}i.push({slug:c,path:a})}return i}async function trr(t,e,r=process.env){let n=r.GITHUB_REPOSITORY_ID,s=r.GITHUB_REPOSITORY;return!n||!s?void 0:(await e(t).catch(()=>{}))?.toLowerCase()===s.toLowerCase()?{[n]:s}:void 0}async function Ztt(){let t=J1();delete process.env.INPUT_SKYRAMPLICENSEFILE;let e=dtt(process.env),r=Ue("skyrampRunId").trim(),n=r?await Vtt(r):void 0;try{await rrr(t,e,n)}finally{n&&await z$(n)}}async function rrr(t,e,r){let n=r!==void 0&&Yle(r);r&&(r.heldInputs=[t.skyrampLicenseFile].filter(Boolean));let s=r?r.layout.repositoryPath:cg.resolve(t.workingDirectory||"."),i=r?()=>r.attempt.token():ptt(),o=r?void 0:e;o&&Ct(o);let a=ltt(),c=new FH({repositoryPath:r?.pullRequest?.path??s,prNumber:a.prNumber,tokenProvider:i,githubToken:o,repoSlug:r?r.pullRequest?.repository??r.layout.repositorySlug:void 0,allowedAuthors:!n&&t.allowedAuthors?.length?t.allowedAuthors:void 0,log:q=>ee(q)});a=utt(a,await c.resolveContext().catch(()=>({}))),ee(`Staged pipeline \u2014 event: ${a.eventName??"?"}${a.action?`/${a.action}`:""}${a.prNumber?`, PR #${a.prNumber}`:""}${a.headRef?` (${a.headRef} \u2192 ${a.baseRef??"?"})`:""}`);let l=id(),u=cg.join(l,"staged");if(a.eventName==="pull_request"&&a.action==="closed"){let q=a.merged===!1,Z=q?`PR #${a.prNumber} was closed without merging`:`PR #${a.prNumber} was merged`;if(q&&a.headRef){let G=await c.closeTestsPr({branch:Ole(a.headRef,Ue("deliverBranch")||void 0),reason:`Closing: the pull request this tests PR targeted (#${a.prNumber}) was closed without being merged.`});G.closed&&(Z+=`; closed the tests PR ${G.url??""}`.trimEnd())}ee(`Staged pipeline \u2014 ${Z}; nothing to run.`);for(let[G,M]of Object.entries(XT({admission:{admit:!1,reason:Z}},{skippedPrClosed:q})))dt(G,M);In("completed","true");return}let d=await c.admitRun();if(!d.admit){ee(`Staged pipeline \u2014 run skipped: ${d.reason}`);for(let[q,Z]of Object.entries(XT({admission:d},{skippedSelfTrigger:!0})))dt(q,Z);In("completed","true");return}let p=r?r.layout.relatedRepos:await err(q=>Ue(q),q=>vm(q),q=>J(q)),m=Ztr(q=>Ue(q));if(m)throw new Error(m);let h=n||Ue("onboard").toLowerCase()==="true",f=ntt(Ue("sutGuidance"),"sutGuidance input"),A;try{A=n?await Jtt(r):CZe(Ue("sutEnvironment"),"sutEnvironment input")}catch(q){throw r&&ZT(),q}for(let q of d$(A))Ct(q);let x=r?Object.fromEntries(r.sources.map(q=>[q.repository.providerRepositoryId,q.slug])):await trr(s,q=>vm(q)),E,C,S=r?.attempt.license?.runToken,v;try{if(e||i){let Z=process.env.GITHUB_WORKSPACE,G=[...new Set([s,...p.map(F=>F.path),...Z?lXe(Z):[]].map(F=>cg.resolve(F)))],M;for(let F of G){let ne=F===cg.resolve(s)?re=>{/^\s*authorization\s*:/i.test(re)&&(M??=re)}:void 0,ye=aXe(F,void 0,ne);ye.length&&ee(`Removed the persisted checkout credential from ${F} (${ye.length} entr${ye.length===1?"y":"ies"}).`)}let $=cXe();$.length&&ee(`Removed ${$.length} persisted checkout credential(s) from RUNNER_TEMP.`),M&&(Ct(M.replace(/^AUTHORIZATION:\s*\S+\s+/i,"")),c.adoptCheckoutAuthHeader(M),ee("Deliver pushes with the credential the checkout was made with."))}else J("No githubToken or GitHub App credentials: the checkout's persisted git credential (if any) is left in place, and the stage sessions can reach it. Set persist-credentials: false on actions/checkout, or pass githubToken.");if(MS.mkdirSync(l,{recursive:!0}),!S){if(v=cg.join(l,"skyramp_license.lic"),!t.skyrampLicenseFile)throw new Error("skyrampLicenseFile input is required");MS.writeFileSync(v,t.skyrampLicenseFile,{mode:384})}let q=await jv(t);E=await tH(q,t,l),C=oU("claude",{model:t.model||void 0,useLocalAuth:t.useLocalAuth&&!t.useBedrock}),await iH(C),await oH(C),C.setupAgentEnv(t,q)}catch(q){r&&ZT();let Z=q instanceof Error?q.message:String(q);await c.createProgressSink().render(OH(Z,{runUrl:c.runUrl})).catch(()=>{}),await c.endRun({status:"failure",summary:`could not start: ${Z}`});for(let[G,M]of Object.entries(XT({admission:{admit:!0},startupError:q instanceof Error?q:new Error(Z)})))dt(G,M);In("completed","true"),Kc(`Skyramp Testbot could not start: ${Z}`);return}t.generatedTestsMode!=="separate-branch"&&J(`pipeline: staged delivers only as a separate tests PR; generatedTestsMode=${t.generatedTestsMode} means nothing is committed or pushed this run`);let B=r?r.attempt.budgetMs(new Date):(t.testbotTimeout||60)*6e4;if(B<=0)throw qtt(),new Error("Testbot V3: setup used the run's whole budget; no time is left before the attempt deadline");let{stages:N,planOnly:Q}=r&&!n?jtt(r.attempt.license?.entitlements):{};Q&&ee("Testbot V3: the organization's entitlements do not include generate; this run is plan-only (analyze and recommend).");let L=await Jet({admission:d,platform:c,watch:r?$tt(r):void 0,log:O$,skipReport:n,run:{runDir:u,fresh:!0,budgetMs:B,...n?{stages:["onboard","deploy"],skipReport:!0,onStageEvent:Ktt(r)}:{},...N?{stages:N}:{},model:Ue("model").trim()||void 0,resolveModel:mtt(t),inputs:{repositoryPath:s,repositorySlug:r?.layout.repositorySlug,pullRequestRepository:r?.pullRequest?.repository,baseBranch:!r&&a.baseRef?`origin/${a.baseRef}`:void 0,relatedRepos:p,headBranch:r?void 0:a.headRef,prTitle:a.title,prDescription:a.body,...r?.pullRequests?.length?{pullRequests:r.pullRequests}:{},planOnly:Q,skyrampMcp:{command:E.command,args:E.args.split(" ").filter(Boolean),licensePath:v,runToken:S},deliver:t.generatedTestsMode==="separate-branch"&&!Q,deliverBranch:Ue("deliverBranch")||void 0,trustedChecks:Xtr(Ue("trustedChecks")),deliverMode:a.eventName==="issue_comment"?"append":"replace",provisionRuntime:!0,runnerPlatform:"github",onboard:h&&!Q,sutGuidance:f,sutEnvironment:A,repositoryIds:x},sessionRunner:ttt(C.binary),sutAuth:{tokenCommand:t.authTokenCommand||void 0,uiCredentials:t.uiCredentials||void 0,sessionEnv:Het(Ue("sessionEnv")),maskSecret:q=>Ct(q),attempts:t.authTokenRetries,retryDelaySec:t.authTokenRetryDelay}}});r&&n?await Xtt(r,L.summary??{},E.nodeModulesDir):r&&await Ytt(r,L.summary??{},E.nodeModulesDir),L.admission.admit&&await ftt(u);let W=XT(L,{skippedSelfTrigger:!L.admission.admit});for(let[q,Z]of Object.entries(W))dt(q,Z);if(In("completed","true"),L.summary){await htt(L.summary,L.outcome),ee(`Staged run ${L.summary.runId}: ${L.outcome?.summary} (state: ${L.summary.stateFilePath})`);let q=U$(L.summary.stateFilePath);q&&(Ds("Stage breakdown (time / cost / context)"),ee(att(q,{order:L.summary.stages.map(Z=>Z.name),wallMinutes:q$(q)})),Sn())}L.startupError?Kc(`Skyramp Testbot could not start: ${L.startupError.message}`):L.outcome&&L.outcome.status==="failure"&&Kc(`Skyramp Testbot: ${L.outcome.summary}`)}var nrr=Ue("pipeline").trim().toLowerCase(),srr=nrr==="staged"?Ztt:kKe;srr().catch(async t=>{Kc(t instanceof Error?t.message:String(t))});
716
+ `)}var Htr="https://testbot.skyramp.dev",ag={attemptId:"v3AttemptId",origin:"v3Origin",deadlineAt:"v3DeadlineAt",reportUploaded:"v3ReportUploaded",recipeUploaded:"v3RecipeUploaded",cause:"v3Cause"},$tr="skyramp-sources",ztr=3e4;function Gtr(t){let e=t.ACTIONS_ID_TOKEN_REQUEST_URL,r=t.ACTIONS_ID_TOKEN_REQUEST_TOKEN;return delete t.ACTIONS_ID_TOKEN_REQUEST_URL,delete t.ACTIONS_ID_TOKEN_REQUEST_TOKEN,async n=>{if(!e||!r)throw new Error("The job cannot request an OIDC token. Give it the `id-token: write` permission.");let s=new URL(e);s.searchParams.set("audience",n);let i=await fetch(s,{headers:{Authorization:`Bearer ${r}`,Accept:"application/json"},redirect:"error",signal:AbortSignal.timeout(ztr)});if(!i.ok)throw new Error(`GitHub refused the OIDC token request: ${i.status}`);let o=(await i.json().catch(()=>({}))).value;if(typeof o!="string"||!o)throw new Error("GitHub's OIDC token response carried no token");return Ct(o),o}}function jtr(t,e){return{origin:t,idToken:e,mask:r=>Ct(r),log:r=>ee(r)}}function Om(t){VI(ag.attemptId)&&!VI(ag.cause)&&In(ag.cause,t)}function ZT(){Om("setup_failed")}function qtt(){Om("timed_out")}var Wle={cancelled:"Skyramp cancelled this run",expired:"this attempt passed its deadline in Skyramp",ended:"Skyramp already ended this attempt"},Htt={cancelled:"cancelled",expired:"timed_out",ended:"agent_failed"};function $tt(t){return e=>Rtt(t.attempt,r=>{Om(Htt[r]),J(`Testbot V3: ${Wle[r]}; stopping the run, and uploading nothing.`),e("attempt-closed",Wle[r])})}async function ztt(t){let e=await Itt(t.attempt);return e?(Om(Htt[e]),J(`Testbot V3: ${Wle[e]}, so nothing is uploaded.`),!0):!1}function Gtt(t){return[...t.attempt.manifest.credentials.map(e=>process.env[e.name]??""),t.attempt.license?.runToken??"",...t.heldInputs??[]].filter(Boolean)}function jtt(t){return!t||t.includes("generate")?{}:{stages:["analyze","recommend"],planOnly:!0}}async function z$(t){t.cancelWatch?.stop();let e=await t.attempt.revokeTokens();for(let r of e)J(`Testbot V3: could not revoke a scoped GitHub token (${r}); it stays valid until it expires.`)}function Vtr(t){let e=["SIGINT","SIGTERM"],r=()=>{n(),z$({attempt:t})},n=()=>{for(let s of e)process.removeListener(s,r)};for(let s of e)process.on(s,r);return{stop:n}}async function Vtt(t){let e=Gtr(process.env),r=Ue("skyrampAppOrigin").trim()||Htr,n=await Ctt(t,process.env,jtr(r,e)),s=Vtr(n);In(ag.attemptId,n.attemptId),In(ag.origin,r),In(ag.deadlineAt,n.deadlineAt.toISOString()),ee(`Testbot V3: attempt ${n.attemptNumber} of Validation Run ${t}, deadline ${n.deadlineAt.toISOString()}`);try{return{...await Wtr(n),cancelWatch:s}}catch(i){throw await z$({attempt:n,cancelWatch:s}),i}}async function Wtr(t){let e=Ftt(t.manifest,process.env);if(e.length>0)throw Om("credential_missing"),new Error(`The workflow does not supply the required credential${e.length>1?"s":""} ${e.join(", ")}. Add ${e.length>1?"them":"it"} to the Testbot step's env.`);let r;try{r=await vtt(t,{workspace:DS.join(process.env.GITHUB_WORKSPACE||process.cwd(),$tr)})}catch(o){throw ZT(),o}for(let o of r)ee(`Testbot V3: ${o.slug} at ${o.revision}`);await Ytr({attempt:t,sources:r});let n=Ptt(r);ee(`Testbot V3: working checkout ${n.repositorySlug}`);let s=Ttt(t.manifest,r);s&&ee(`Testbot V3: the pull request is ${s.repository}#${s.number}`);let i=await Btt(t);for(let o of i)ee([`Testbot V3: Change Set ${o.repository}#${o.number}`,o.note].filter(Boolean).join(": "));return{attempt:t,sources:r,layout:n,pullRequests:i,pullRequest:s}}async function Ytr(t){for(let e of t.sources)jle(e.path);Yle(t)||await Jtr(t)}async function Jtr(t){let e=t.sources[0],r;try{r=await Qtt(t.attempt)}catch(n){if(!(n instanceof UE&&n.status===404))throw ZT(),n;J(`Testbot V3: this Skyramp app does not serve the stored SUT recipe (${n.message}); deploy uses a source's own recipe, if one has it.`);return}if(!r){ee("Testbot V3: no stored SUT recipe for this Target yet; deploy uses a source's own recipe, if one has it.");return}Utt(e.path,r.files),ee(`Testbot V3: SUT recipe version ${r.version}, ${r.files.length} files, for ${e.slug} (uncommitted)`)}function Wtt(t){try{let e=JSON.parse(QS.readFileSync(DS.join(t,"@skyramp","mcp","package.json"),"utf-8")).version;return typeof e=="string"&&/^[0-9A-Za-z.+-]{1,64}$/.test(e)?e:"unknown"}catch{return"unknown"}}async function Ytt(t,e,r){e.aborted?Om("cancelled"):e.timedOut&&Om("timed_out");let n=e.outputsDir?DS.join(e.outputsDir,"report.json"):void 0;if(!n||!QS.existsSync(n)){J("Testbot V3: the run wrote no report, so Skyramp records it as an infrastructure error.");return}if(!await ztt(t))try{let s=JSON.parse(QS.readFileSync(n,"utf-8"));await _tt(t.attempt,{report:s,sources:t.sources,workingSlug:t.layout.repositorySlug,delivery:Ltt(e.outputsDir,t.sources,s,t.layout.repositorySlug),producer:{testbot:nH().version,mcp:Wtt(r)},secrets:Gtt(t)}),In(ag.reportUploaded,"true"),ee("Testbot V3: report uploaded; Skyramp derives the outcome.")}catch(s){J(`Testbot V3: the report upload failed: ${s instanceof Error?s.message:String(s)}`)}}function Yle(t){return t.attempt.manifest.trigger.kind==="sut_setup"}async function Jtt(t){let{capture:e}=await Dtt(t.attempt);return ile(e.settings.target.environment,"the run's SUT / Environment settings")}var Ktr={onboard:"onboard",deploy:"deploy"};function Ktt(t){return({stage:e,event:r,status:n})=>{let s=Ktr[e];if(!s)return;let i=r==="finished",o=n==="aborted"?"skipped":n;Mtt(t.attempt,{schemaVersion:1,stage:s,event:i?"finished":"started",...i&&o?{status:o}:{}}).catch(a=>J(`Testbot V3: could not report ${e} ${r}: ${a instanceof Error?a.message:String(a)}`))}}var Vle=t=>{try{return JSON.parse(QS.readFileSync(t,"utf-8"))}catch{return}};async function Xtt(t,e,r){e.aborted?Om("cancelled"):e.timedOut&&Om("timed_out");let n=e.outputsDir?Vle(DS.join(e.outputsDir,"onboard.json")):void 0;if(!n){J("Testbot V3: onboard wrote no answer, so there is no SUT recipe to send; Skyramp records the run as an infrastructure error.");return}if(await ztt(t))return;let s=Vle(DS.join(e.outputsDir,"deploy.json")),o=(e.stateFilePath?Vle(e.stateFilePath):void 0)?.stages.deploy?.attempts?.reduce((a,c)=>a+(c.totalMs??c.durationMs??0),0);try{let a=sZe(n,s,{deployDurationSeconds:o?Math.round(o/1e3):void 0,recipeFiles:s?ole(t.layout.repositoryPath):void 0});await Ott(t.attempt,{recipe:a,sources:t.sources,producer:{testbot:nH().version,mcp:Wtt(r)},secrets:Gtt(t)}),In(ag.recipeUploaded,"true"),ee(`Testbot V3: SUT recipe uploaded (${a.status}); Skyramp derives the outcome.`)}catch(a){J(`Testbot V3: the SUT recipe upload failed: ${a instanceof Error?a.message:String(a)}`)}}function Xtr(t){let e=t.split(/[\n,]/).map(r=>r.trim()).filter(Boolean);return e.length?e:void 0}function Ztr(t){if((t("testRepoPath")??"").trim())return"testRepoPath is not supported by the staged pipeline (pipeline: staged) \u2014 it writes tests into the application checkout only, and the Action's token has no write access to another repository. Use pipeline: classic for cross-repository delivery, or remove the input."}async function err(t,e,r,n=process.env.GITHUB_WORKSPACE||process.cwd()){let s=(t("relatedRepoPaths")??"").trim();if(!s)return[];let i=[];for(let o of s.split(/[\n,]/).map(a=>a.trim()).filter(Boolean)){let a=cg.resolve(n,o);if(!yo(n,o)){r(`relatedRepoPaths: ${o} is outside the workspace \u2014 skipping`);continue}if(!MS.existsSync(a)){r(`relatedRepoPaths: no checkout at ${o} \u2014 skipping`);continue}let c=await e(a);if(!c){r(`relatedRepoPaths: could not resolve owner/repo for ${o} (no origin remote?) \u2014 skipping`);continue}i.push({slug:c,path:a})}return i}async function trr(t,e,r=process.env){let n=r.GITHUB_REPOSITORY_ID,s=r.GITHUB_REPOSITORY;return!n||!s?void 0:(await e(t).catch(()=>{}))?.toLowerCase()===s.toLowerCase()?{[n]:s}:void 0}async function Ztt(){let t=J1();delete process.env.INPUT_SKYRAMPLICENSEFILE;let e=dtt(process.env),r=Ue("skyrampRunId").trim(),n=r?await Vtt(r):void 0;try{await rrr(t,e,n)}finally{n&&await z$(n)}}async function rrr(t,e,r){let n=r!==void 0&&Yle(r);r&&(r.heldInputs=[t.skyrampLicenseFile].filter(Boolean));let s=r?r.layout.repositoryPath:cg.resolve(t.workingDirectory||"."),i=r?()=>r.attempt.token():ptt(),o=r?void 0:e;o&&Ct(o);let a=ltt(),c=new FH({repositoryPath:r?.pullRequest?.path??s,prNumber:a.prNumber,tokenProvider:i,githubToken:o,repoSlug:r?r.pullRequest?.repository??r.layout.repositorySlug:void 0,allowedAuthors:!n&&t.allowedAuthors?.length?t.allowedAuthors:void 0,log:q=>ee(q)});a=utt(a,await c.resolveContext().catch(()=>({}))),ee(`Staged pipeline \u2014 event: ${a.eventName??"?"}${a.action?`/${a.action}`:""}${a.prNumber?`, PR #${a.prNumber}`:""}${a.headRef?` (${a.headRef} \u2192 ${a.baseRef??"?"})`:""}`);let l=id(),u=cg.join(l,"staged");if(a.eventName==="pull_request"&&a.action==="closed"){let q=a.merged===!1,Z=q?`PR #${a.prNumber} was closed without merging`:`PR #${a.prNumber} was merged`;if(q&&a.headRef){let G=await c.closeTestsPr({branch:Ole(a.headRef,Ue("deliverBranch")||void 0),reason:`Closing: the pull request this tests PR targeted (#${a.prNumber}) was closed without being merged.`});G.closed&&(Z+=`; closed the tests PR ${G.url??""}`.trimEnd())}ee(`Staged pipeline \u2014 ${Z}; nothing to run.`);for(let[G,M]of Object.entries(XT({admission:{admit:!1,reason:Z}},{skippedPrClosed:q})))dt(G,M);In("completed","true");return}let d=await c.admitRun();if(!d.admit){ee(`Staged pipeline \u2014 run skipped: ${d.reason}`);for(let[q,Z]of Object.entries(XT({admission:d},{skippedSelfTrigger:!0})))dt(q,Z);In("completed","true");return}let p=r?r.layout.relatedRepos:await err(q=>Ue(q),q=>vm(q),q=>J(q)),m=Ztr(q=>Ue(q));if(m)throw new Error(m);let h=n||Ue("onboard").toLowerCase()==="true",f=ntt(Ue("sutGuidance"),"sutGuidance input"),A;try{A=n?await Jtt(r):CZe(Ue("sutEnvironment"),"sutEnvironment input")}catch(q){throw r&&ZT(),q}for(let q of d$(A))Ct(q);let x=r?Object.fromEntries(r.sources.map(q=>[q.repository.providerRepositoryId,q.slug])):await trr(s,q=>vm(q)),E,C,S=r?.attempt.license?.runToken,v;try{if(e||i){let Z=process.env.GITHUB_WORKSPACE,G=[...new Set([s,...p.map(F=>F.path),...Z?lXe(Z):[]].map(F=>cg.resolve(F)))],M;for(let F of G){let ne=F===cg.resolve(s)?re=>{/^\s*authorization\s*:/i.test(re)&&(M??=re)}:void 0,ye=aXe(F,void 0,ne);ye.length&&ee(`Removed the persisted checkout credential from ${F} (${ye.length} entr${ye.length===1?"y":"ies"}).`)}let $=cXe();$.length&&ee(`Removed ${$.length} persisted checkout credential(s) from RUNNER_TEMP.`),M&&(Ct(M.replace(/^AUTHORIZATION:\s*\S+\s+/i,"")),c.adoptCheckoutAuthHeader(M),ee("Deliver pushes with the credential the checkout was made with."))}else J("No githubToken or GitHub App credentials: the checkout's persisted git credential (if any) is left in place, and the stage sessions can reach it. Set persist-credentials: false on actions/checkout, or pass githubToken.");if(MS.mkdirSync(l,{recursive:!0}),!S){if(v=cg.join(l,"skyramp_license.lic"),!t.skyrampLicenseFile)throw new Error("skyrampLicenseFile input is required");MS.writeFileSync(v,t.skyrampLicenseFile,{mode:384})}let q=await jv(t);E=await tH(q,t,l),C=oU("claude",{model:t.model||void 0,useLocalAuth:t.useLocalAuth&&!t.useBedrock}),await iH(C),await oH(C),C.setupAgentEnv(t,q)}catch(q){r&&ZT();let Z=q instanceof Error?q.message:String(q);await c.createProgressSink().render(OH(Z,{runUrl:c.runUrl})).catch(()=>{}),await c.endRun({status:"failure",summary:`could not start: ${Z}`});for(let[G,M]of Object.entries(XT({admission:{admit:!0},startupError:q instanceof Error?q:new Error(Z)})))dt(G,M);In("completed","true"),Kc(`Skyramp Testbot could not start: ${Z}`);return}t.generatedTestsMode!=="separate-branch"&&J(`pipeline: staged delivers only as a separate tests PR; generatedTestsMode=${t.generatedTestsMode} means nothing is committed or pushed this run`);let B=r?r.attempt.budgetMs(new Date):(t.testbotTimeout||60)*6e4;if(B<=0)throw qtt(),new Error("Testbot V3: setup used the run's whole budget; no time is left before the attempt deadline");let{stages:N,planOnly:Q}=r&&!n?jtt(r.attempt.license?.entitlements):{};Q&&ee("Testbot V3: this organization's plan does not include test generation, so this run only analyzes the change and recommends tests.");let L=await Jet({admission:d,platform:c,watch:r?$tt(r):void 0,log:O$,skipReport:n,run:{runDir:u,fresh:!0,budgetMs:B,...n?{stages:["onboard","deploy"],skipReport:!0,onStageEvent:Ktt(r)}:{},...N?{stages:N}:{},model:Ue("model").trim()||void 0,resolveModel:mtt(t),inputs:{repositoryPath:s,repositorySlug:r?.layout.repositorySlug,pullRequestRepository:r?.pullRequest?.repository,baseBranch:!r&&a.baseRef?`origin/${a.baseRef}`:void 0,relatedRepos:p,headBranch:r?void 0:a.headRef,prTitle:a.title,prDescription:a.body,...r?.pullRequests?.length?{pullRequests:r.pullRequests}:{},planOnly:Q,skyrampMcp:{command:E.command,args:E.args.split(" ").filter(Boolean),licensePath:v,runToken:S},deliver:t.generatedTestsMode==="separate-branch"&&!Q,deliverBranch:Ue("deliverBranch")||void 0,trustedChecks:Xtr(Ue("trustedChecks")),deliverMode:a.eventName==="issue_comment"?"append":"replace",provisionRuntime:!0,runnerPlatform:"github",onboard:h&&!Q,sutGuidance:f,sutEnvironment:A,repositoryIds:x},sessionRunner:ttt(C.binary),sutAuth:{tokenCommand:t.authTokenCommand||void 0,uiCredentials:t.uiCredentials||void 0,sessionEnv:Het(Ue("sessionEnv")),maskSecret:q=>Ct(q),attempts:t.authTokenRetries,retryDelaySec:t.authTokenRetryDelay}}});r&&n?await Xtt(r,L.summary??{},E.nodeModulesDir):r&&await Ytt(r,L.summary??{},E.nodeModulesDir),L.admission.admit&&await ftt(u);let W=XT(L,{skippedSelfTrigger:!L.admission.admit});for(let[q,Z]of Object.entries(W))dt(q,Z);if(In("completed","true"),L.summary){await htt(L.summary,L.outcome),ee(`Staged run ${L.summary.runId}: ${L.outcome?.summary} (state: ${L.summary.stateFilePath})`);let q=U$(L.summary.stateFilePath);q&&(Ds("Stage breakdown (time / cost / context)"),ee(att(q,{order:L.summary.stages.map(Z=>Z.name),wallMinutes:q$(q)})),Sn())}L.startupError?Kc(`Skyramp Testbot could not start: ${L.startupError.message}`):L.outcome&&L.outcome.status==="failure"&&Kc(`Skyramp Testbot: ${L.outcome.summary}`)}var nrr=Ue("pipeline").trim().toLowerCase(),srr=nrr==="staged"?Ztt:kKe;srr().catch(async t=>{Kc(t instanceof Error?t.message:String(t))});
717
717
  /*! Bundled license information:
718
718
 
719
719
  undici/lib/web/fetch/body.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyramp/testbot-core",
3
- "version": "0.12.0-v3.15",
3
+ "version": "0.12.0-v3.16",
4
4
  "description": "Skyramp Testbot engine: AI-powered deterministic test generation, execution and maintenance",
5
5
  "main": "dist/main.js",
6
6
  "//files": "An explicit allowlist, never a glob. `dist/` is gitignored, so without this key npm's .gitignore fallback would publish a package with no engine in it; with a glob it would publish the sourcemaps, whose sourcesContent embeds every src/*.ts verbatim. eval-entry.js is a development entry and must not ship.",