@radhya/mach 1.8.1 → 1.8.3

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 CHANGED
@@ -330,6 +330,8 @@ When `android.versionCode` is set to `"auto"`, Mach performs the Google Play loo
330
330
 
331
331
  Dev-client builds should keep `distribution: "internal"` and set `developmentClient: true`. Mach will use development signing credentials for those builds while still producing an internal installable artifact.
332
332
 
333
+ For Android dev-client builds, Mach defaults to Gradle `assembleDebug` so the output opens the Metro/debug server instead of behaving like a standalone release APK. For iOS dev-client builds, Mach uses the Debug Xcode configuration.
334
+
333
335
  ## Store Submission
334
336
 
335
337
  ```bash
package/dist/index.js CHANGED
@@ -346,6 +346,10 @@ if [ ! -z "$ANDROID_VERSION_CODE" ]; then
346
346
  SIGNING_FLAGS+=( "-Pandroid.injected.version.code=$ANDROID_VERSION_CODE" )
347
347
  fi
348
348
 
349
+ echo "[DISK] Before Gradle build:"
350
+ df -h /
351
+ du -sh /home/ubuntu/build /root/.gradle /root/.npm 2>/dev/null || true
352
+
349
353
  $GRADLEW {{BUILD_COMMAND}} "\${SIGNING_FLAGS[@]}" --console=plain --no-daemon 2>&1
350
354
  BUILD_EXIT_CODE=$?
351
355
 
@@ -483,7 +487,7 @@ for pid in "\${cache_pids[@]}"; do wait "$pid" || true; done
483
487
  echo "Build orchestrator finished. Auto-terminating instance in 5 seconds..."
484
488
  sleep 5
485
489
  sudo shutdown -h now
486
- `;var Di=async(e,t,i={},n,o)=>{let r=co(),l=e.buildProfile||"production",a=l==="production",s=e.apk===!0,c=a?"bundleRelease":"assembleRelease",d=e.buildCommand||(s?"assembleRelease":c),u=e.nodeVersion?[`echo "[NODE] Switching to Node ${e.nodeVersion}..."`,`CURRENT_MAJOR=$(node -e "process.stdout.write(process.version.split('.')[0].replace('v',''))" 2>/dev/null || echo "0")`,`if [ "$CURRENT_MAJOR" != "${e.nodeVersion}" ]; then`,` curl -fsSL https://deb.nodesource.com/setup_${e.nodeVersion}.x | bash - 2>&1`," apt-get install -y nodejs 2>&1",' echo "[NODE] Installed Node $(node -v)"',"else",' echo "[NODE] Already on Node $(node -v) \u2014 no switch needed"',"fi"].join(`
490
+ `;var Di=async(e,t,i={},n,o)=>{let r=co(),l=e.buildProfile||"production",a=l==="production",s=e.apk===!0,c=e.developmentClient?"assembleDebug":a?"bundleRelease":"assembleRelease",d=e.buildCommand||(s?"assembleRelease":c),u=e.nodeVersion?[`echo "[NODE] Switching to Node ${e.nodeVersion}..."`,`CURRENT_MAJOR=$(node -e "process.stdout.write(process.version.split('.')[0].replace('v',''))" 2>/dev/null || echo "0")`,`if [ "$CURRENT_MAJOR" != "${e.nodeVersion}" ]; then`,` curl -fsSL https://deb.nodesource.com/setup_${e.nodeVersion}.x | bash - 2>&1`," apt-get install -y nodejs 2>&1",' echo "[NODE] Installed Node $(node -v)"',"else",' echo "[NODE] Already on Node $(node -v) \u2014 no switch needed"',"fi"].join(`
487
491
  `):"",p;if(o){let E=$i.isAbsolute(o)?o:$i.resolve(process.cwd(),o);Pi.existsSync(E)?(p=Pi.readFileSync(E,"utf-8"),bt.info(_i.magenta(`\u2713 Loaded preBuild hook: ${o}`))):bt.warn(`preBuild script not found at ${E} \u2014 skipping`)}let g=Ii.replace(/\{\{BUILD_ID\}\}/g,t).replace(/\{\{BUILD_COMMAND\}\}/g,d).replace("{{NODE_VERSION_SETUP}}",u).replace("{{ENV_VARS}}",`
488
492
  export MACH_APP_NAME="${e.appName||"App"}"
489
493
  export MACH_BUILD_PROFILE="${l}"
@@ -969,7 +973,7 @@ end
969
973
  \u2713 Local build completed successfully in ${ne}`)),await c("building",{...K&&{bundleId:K},...H&&{appName:H}}),z.length>0&&(A.info(h.cyan(`
970
974
  \u{1F4E6} Generated Artifacts:`)),z.forEach(T=>{let k=_.resolve(T);A.info(h.dim(` - ${T}`)),A.info(h.gray(` Path: ${k}`))}),e.interactive)){let T=await go({message:"Install on connected device?"});if(!_t(T)&&T){if(a==="android"){let k=z.find(V=>V.endsWith(".apk"))||z[0];await Ro(k,V=>U(V))}else if(a==="ios"){let k=z.find(N=>N.endsWith(".ipa"))||z.find(N=>N.endsWith(".app"))||z[0],V=Te("ios");e.simulator?await wo(k,V||"",N=>U(N)):await vo(k,V||"",N=>U(N))}}}await b("upload");let he=[];for(let T of z)try{let k=_.join(_e.tmpdir(),`${t}-${_.basename(T)}`);S.copyFileSync(T,k),he.push(k),A.info(h.dim(` \u{1F4CB} Preserved artifact: ${_.basename(T)}`))}catch{A.warn(h.yellow(` Failed to preserve artifact: ${_.basename(T)}`))}z=he,A.info(h.dim("\u{1F9F9} Cleaning workspace (preserving dependency cache)..."));try{let T=process.cwd(),k=new Set(["node_modules"]),V=S.readdirSync(T),N=0;for(let oe of V)if(!k.has(oe)){if(oe==="ios"){let J=_.join(T,"ios"),X=S.readdirSync(J);for(let le of X)if(le!=="Pods")try{S.rmSync(_.join(J,le),{recursive:!0,force:!0}),N++}catch{}continue}try{S.rmSync(_.join(T,oe),{recursive:!0,force:!0}),N++}catch{}}A.info(h.dim(` Cleaned ${N} items. Cached: node_modules${S.existsSync(_.join(T,"ios","Pods"))?", ios/Pods":""}`)),A.info(h.green("\u{1F512} Security: No source code retained on build server. Only public dependencies cached."))}catch{A.warn(h.yellow("Post-build cleanup encountered errors (non-fatal)."))}try{let k=_.join(_e.homedir(),f.workspacesDir),V=G(`df -k "${k}" | tail -1 | awk '{print $4}'`,{encoding:"utf8"}).trim(),N=parseInt(V,10)*1024;if(N<53687091200&&S.existsSync(k)){A.info(h.dim(` \u26A0\uFE0F Low disk space (${(N/1024/1024/1024).toFixed(0)} GB free). Running cache eviction...`));let oe=_.basename(process.cwd()),J=S.readdirSync(k).filter(X=>X!==oe).map(X=>{let le=_.join(k,X);try{let Ie=S.statSync(le);return Ie.isDirectory()?{name:X,dir:le,mtime:Ie.mtimeMs}:null}catch{return null}}).filter(Boolean);J.sort((X,le)=>X.mtime-le.mtime);for(let X of J){if(N>=53687091200)break;try{S.rmSync(X.dir,{recursive:!0,force:!0}),A.info(h.dim(` \u{1F5D1}\uFE0F Evicted stale workspace: ${X.name}`));let le=G(`df -k "${k}" | tail -1 | awk '{print $4}'`,{encoding:"utf8"}).trim();if(parseInt(le,10)*1024>=53687091200)break}catch{}}}}catch{}return await w(),z}catch(m){throw await w(),m.message==="Command aborted"?(A.warn(h.yellow(`
971
975
  \u274C Build aborted.`)),await c("failed",{error:"Aborted by user"}),m):(A.error(h.red(`
972
- \u2717 Local build failed: ${m.message}`)),await c("failed",{error:m.message}),m)}},Po=async(e,t,i={},n,o)=>{let r=S.existsSync("android/gradlew")?"android/gradlew":S.existsSync("gradlew")?"./gradlew":null;if(!r)throw new Error("Could not find gradlew. Is this an Android project?");let l="assembleRelease";e.distribution==="store"?l="bundleRelease":e.distribution==="internal"&&(l="assembleRelease");let a=e.buildCommand||l;A.info(h.blue(`Running Android build: ${a}...`));let s=r.includes("android/")?"android":".",c=(r.includes("android/"),"./gradlew"),d=[a];if(i.ANDROID_VERSION_CODE){let p=_.join(s,"app/build.gradle");if(S.existsSync(p)){let g=i.ANDROID_VERSION_CODE,E=S.readFileSync(p,"utf-8");E=E.replace(/versionCode\s+\d+/,`versionCode ${g}`),S.writeFileSync(p,E),A.info(h.green(`\u2713 Applied Android versionCode ${g}`))}d.push(`-Pandroid.injected.version.code=${i.ANDROID_VERSION_CODE}`)}await Oe(c,d,s,i,n,o);let u=_.join(s,"app/build/outputs");return Ve(u,[".apk",".aab"])},$o=async(e,t,i,n={},o,r,l,a,s)=>{if(process.platform!=="darwin")throw new Error("iOS builds can only be run on macOS.");let c=_.resolve(process.cwd(),S.existsSync("ios")?"ios":"."),d=S.readdirSync(c),u=d.find(w=>w.endsWith(".xcworkspace")),p=d.find(w=>w.endsWith(".xcodeproj"));if(!u&&!p)throw new Error("Could not find Xcode workspace or project in ios/ directory.");try{let w=G("xcode-select -p").toString().trim();A.info(h.dim(`Using Xcode at: ${w}`))}catch{A.warn(h.dim("Could not detect Xcode path."))}A.info(h.blue("Running iOS build via xcodebuild..."));let g=u?u.replace(".xcworkspace",""):p?.replace(".xcodeproj",""),E=e.iosScheme||g||e.scheme,P=e.developmentClient?"Debug":e.iosConfiguration||"Release",C=(o||"default").replace(/[^a-zA-Z0-9-_]/g,"_"),B=_.join(_e.homedir(),`Library/Developer/Xcode/DerivedData/${f.nameLower}`,C);if(S.mkdirSync(B,{recursive:!0}),e.simulator){A.info(h.dim(`Building for simulator (Scheme: ${E}, Config: ${P})...`)),await Oe("xcodebuild",[u?"-workspace":"-project",u||p,"-scheme",E,"-configuration",P,"-sdk","iphonesimulator","-derivedDataPath",B,"CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO"],c,n,r,l);let w=_.join(B,"Build/Products",`${P}-iphonesimulator`),U=Ve(w,[".app"]);if(U.length>0){let b=U[0],L=_.basename(b,".app"),m=_.join(w,`${L}_simulator.zip`);return A.info(h.dim(`Creating simulator artifact: ${m}...`)),G(`cd "${w}" && zip -r "${m}" "${_.basename(b)}"`),[m]}return[]}else{A.info(h.dim(`Archiving (Scheme: ${E}, Config: ${P})...`));let w=_.join(c,"build.xcarchive"),U=_.join(c,"export"),b=n.IOS_DIST_P12,L=n.IOS_PROVISIONING_PROFILE,m=n.IOS_P12_PASSWORD||"",D=[],y,I,x={isAppStore:!1,isDevelopment:!1};if(b&&L){A.info(h.blue("\u{1F510} CI/CD Signing: Importing certificates..."));try{let H=`${f.buildPrefix}-${t}.keychain-db`,z=_.join(_e.tmpdir(),H),ne=f.keychainPassword;G(`security create-keychain -p "${ne}" "${z}" 2>/dev/null || true`),G(`security set-keychain-settings -t 3600 -l "${z}"`),G(`security unlock-keychain -p "${ne}" "${z}"`);let he=_.join(_e.tmpdir(),`cert-${t}.p12`),T=Buffer.from(b,"base64");S.writeFileSync(he,T),A.info(h.dim(`P12 data size: ${T.length} bytes, first bytes: ${T.slice(0,4).toString("hex")}`)),(T.length<100||T[0]!==48)&&(A.warn(h.yellow("\u26A0\uFE0F P12 data looks corrupted or was not decrypted correctly.")),A.warn(h.yellow(" This usually means MACH_ENCRYPTION_KEY on the Remote API differs from when credentials were uploaded.")));let k=[m,"",f.keychainPassword],V=!1;for(let ce of k)try{G(`security import "${he}" -k "${z}" -P "${ce}" -A -T /usr/bin/codesign -T /usr/bin/security`,{stdio:"pipe"}),V=!0,A.info(h.dim(`\u2713 P12 imported successfully with password: ${ce?"[set]":"[empty]"}`));break}catch(de){A.info(h.dim(` P12 import attempt with password ${ce?`"${ce.substring(0,3)}..."`:"[empty]"} failed: ${de.message?.split(`
976
+ \u2717 Local build failed: ${m.message}`)),await c("failed",{error:m.message}),m)}},Po=async(e,t,i={},n,o)=>{let r=S.existsSync("android/gradlew")?"android/gradlew":S.existsSync("gradlew")?"./gradlew":null;if(!r)throw new Error("Could not find gradlew. Is this an Android project?");let l=e.developmentClient?"assembleDebug":"assembleRelease";!e.developmentClient&&e.distribution==="store"?l="bundleRelease":!e.developmentClient&&e.distribution==="internal"&&(l="assembleRelease");let a=e.buildCommand||l;A.info(h.blue(`Running Android build: ${a}...`));let s=r.includes("android/")?"android":".",c=(r.includes("android/"),"./gradlew"),d=[a];if(i.ANDROID_VERSION_CODE){let p=_.join(s,"app/build.gradle");if(S.existsSync(p)){let g=i.ANDROID_VERSION_CODE,E=S.readFileSync(p,"utf-8");E=E.replace(/versionCode\s+\d+/,`versionCode ${g}`),S.writeFileSync(p,E),A.info(h.green(`\u2713 Applied Android versionCode ${g}`))}d.push(`-Pandroid.injected.version.code=${i.ANDROID_VERSION_CODE}`)}await Oe(c,d,s,i,n,o);let u=_.join(s,"app/build/outputs");return Ve(u,[".apk",".aab"])},$o=async(e,t,i,n={},o,r,l,a,s)=>{if(process.platform!=="darwin")throw new Error("iOS builds can only be run on macOS.");let c=_.resolve(process.cwd(),S.existsSync("ios")?"ios":"."),d=S.readdirSync(c),u=d.find(w=>w.endsWith(".xcworkspace")),p=d.find(w=>w.endsWith(".xcodeproj"));if(!u&&!p)throw new Error("Could not find Xcode workspace or project in ios/ directory.");try{let w=G("xcode-select -p").toString().trim();A.info(h.dim(`Using Xcode at: ${w}`))}catch{A.warn(h.dim("Could not detect Xcode path."))}A.info(h.blue("Running iOS build via xcodebuild..."));let g=u?u.replace(".xcworkspace",""):p?.replace(".xcodeproj",""),E=e.iosScheme||g||e.scheme,P=e.developmentClient?"Debug":e.iosConfiguration||"Release",C=(o||"default").replace(/[^a-zA-Z0-9-_]/g,"_"),B=_.join(_e.homedir(),`Library/Developer/Xcode/DerivedData/${f.nameLower}`,C);if(S.mkdirSync(B,{recursive:!0}),e.simulator){A.info(h.dim(`Building for simulator (Scheme: ${E}, Config: ${P})...`)),await Oe("xcodebuild",[u?"-workspace":"-project",u||p,"-scheme",E,"-configuration",P,"-sdk","iphonesimulator","-derivedDataPath",B,"CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO"],c,n,r,l);let w=_.join(B,"Build/Products",`${P}-iphonesimulator`),U=Ve(w,[".app"]);if(U.length>0){let b=U[0],L=_.basename(b,".app"),m=_.join(w,`${L}_simulator.zip`);return A.info(h.dim(`Creating simulator artifact: ${m}...`)),G(`cd "${w}" && zip -r "${m}" "${_.basename(b)}"`),[m]}return[]}else{A.info(h.dim(`Archiving (Scheme: ${E}, Config: ${P})...`));let w=_.join(c,"build.xcarchive"),U=_.join(c,"export"),b=n.IOS_DIST_P12,L=n.IOS_PROVISIONING_PROFILE,m=n.IOS_P12_PASSWORD||"",D=[],y,I,x={isAppStore:!1,isDevelopment:!1};if(b&&L){A.info(h.blue("\u{1F510} CI/CD Signing: Importing certificates..."));try{let H=`${f.buildPrefix}-${t}.keychain-db`,z=_.join(_e.tmpdir(),H),ne=f.keychainPassword;G(`security create-keychain -p "${ne}" "${z}" 2>/dev/null || true`),G(`security set-keychain-settings -t 3600 -l "${z}"`),G(`security unlock-keychain -p "${ne}" "${z}"`);let he=_.join(_e.tmpdir(),`cert-${t}.p12`),T=Buffer.from(b,"base64");S.writeFileSync(he,T),A.info(h.dim(`P12 data size: ${T.length} bytes, first bytes: ${T.slice(0,4).toString("hex")}`)),(T.length<100||T[0]!==48)&&(A.warn(h.yellow("\u26A0\uFE0F P12 data looks corrupted or was not decrypted correctly.")),A.warn(h.yellow(" This usually means MACH_ENCRYPTION_KEY on the Remote API differs from when credentials were uploaded.")));let k=[m,"",f.keychainPassword],V=!1;for(let ce of k)try{G(`security import "${he}" -k "${z}" -P "${ce}" -A -T /usr/bin/codesign -T /usr/bin/security`,{stdio:"pipe"}),V=!0,A.info(h.dim(`\u2713 P12 imported successfully with password: ${ce?"[set]":"[empty]"}`));break}catch(de){A.info(h.dim(` P12 import attempt with password ${ce?`"${ce.substring(0,3)}..."`:"[empty]"} failed: ${de.message?.split(`
973
977
  `)[0]||"unknown"}`))}if(!V)throw new Error("Failed to import P12.");S.unlinkSync(he),G(`security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${ne}" "${z}"`);let N=G("security list-keychains -d user",{encoding:"utf-8"}).split(`
974
978
  `).map(ce=>ce.trim().replace(/^"|"$/g,"")).filter(ce=>ce.length>0),oe=[z,...N].map(ce=>`"${ce}"`).join(" ");G(`security list-keychains -d user -s ${oe}`),G(`security default-keychain -s "${z}"`);let J=_.join(_e.homedir(),"Library/MobileDevice/Provisioning Profiles");S.mkdirSync(J,{recursive:!0});let X=Buffer.from(L,"base64"),le=_.join(J,`${f.nameLower}-temp-${t}.mobileprovision`);S.writeFileSync(le,X);let Ie=X.toString("utf-8"),Ze=/<key>get-task-allow<\/key>\s*<true\/>/.test(Ie);x={isAppStore:!Ie.includes("<key>ProvisionedDevices</key>")&&!Ze,isDevelopment:Ze};try{let de=G(`security cms -D -i "${le}"`,{encoding:"utf-8"}).match(/<key>UUID<\/key>\s*<string>([^<]+)<\/string>/);I=de?de[1]:void 0}catch{let de=Ie.match(/<key>UUID<\/key>\s*<string>([^<]+)<\/string>/);I=de?de[1]:void 0}I||(A.warn("Could not extract UUID from provisioning profile. Using fallback."),I=`${f.nameLower}-${t}`);let Ge=_.join(J,`${I}.mobileprovision`);S.existsSync(Ge)&&S.unlinkSync(Ge),S.renameSync(le,Ge);try{let de=G(`security find-identity -v -p codesigning "${z}"`,{encoding:"utf-8"}).match(/"((?:Apple|iPhone) (?:Distribution|Developer|Development)[^"]*)"/);de&&(y=de[1],A.info(h.blue(`Identity auto-detected from keychain: "${y}"`)))}catch{}y||(y=x.isDevelopment?"Apple Development":"Apple Distribution",A.info(h.blue(`Identity fallback (profile heuristic): "${y}"`))),A.info(h.dim(`Profile type: ${x.isDevelopment?"Development":x.isAppStore?"App Store":"Ad-Hoc"}`)),A.info(h.dim(`Identity Detection: get-task-allow=${x.isDevelopment}, Selected Identity="${y}"`)),D.push("CODE_SIGN_STYLE=Manual"),D.push(`CODE_SIGN_IDENTITY="${y}"`),D.push(`PROVISIONING_PROFILE_SPECIFIER=${I}`),e.iosTeamId&&D.push(`DEVELOPMENT_TEAM=${e.iosTeamId}`)}catch(H){throw A.error(`Signing setup failed: ${H.message}`),H}}else D.push("-allowProvisioningUpdates"),e.iosTeamId&&D.push(`DEVELOPMENT_TEAM=${e.iosTeamId}`);s&&await s("archive"),A.info(h.blue(`Archive detected Identity: "${y}"`)),A.info(h.blue(`Archive detected UUID: "${I}"`)),await Oe("xcodebuild",["archive",u?"-workspace":"-project",u||p,"-scheme",E,"-configuration",P,"-archivePath",w,"-derivedDataPath",B,...D],c,n,r,l);let W;I?(x.isAppStore?W="app-store":x.isDevelopment?W="development":W="ad-hoc",A.info(h.blue(`Export method from profile: "${W}"`))):(W=e.distribution==="store"?"app-store":e.distribution==="internal"?"ad-hoc":"development",A.warn(h.yellow(`No profile UUID detected. Export method from distribution flag: "${W}"`)));let j=e.iosExportMethod||W,O=Te("ios"),F=_.join(c,"ExportOptions.plist"),M=`<?xml version="1.0" encoding="UTF-8"?>
975
979
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -1001,7 +1005,7 @@ ${M}`)),s&&await s("export"),A.info(h.blue(`Exporting with Bundle ID: "${O}"`)),
1001
1005
  `),new Error(ne)}return K}},Te=e=>{try{let t=_.join(process.cwd(),f.configFileName);if(S.existsSync(t)){let i=JSON.parse(S.readFileSync(t,"utf-8"));if(e==="android"&&i.android?.package)return i.android.package;if(e==="ios"&&i.ios?.bundleIdentifier)return i.ios.bundleIdentifier}if(e==="android"){let i=["android/app/build.gradle","app/build.gradle","build.gradle"];for(let n of i)if(S.existsSync(n)){let r=S.readFileSync(n,"utf-8").match(/applicationId\s+['"]([^'"]+)['"]/);if(r)return r[1]}}else{let i=_.resolve(process.cwd(),S.existsSync("ios")?"ios":"."),n=Ve(i,["Info.plist"]).filter(l=>!l.includes("/Pods/")&&!l.includes("/build/")&&!l.includes("/DerivedData/"));n.sort((l,a)=>a.split("/").length-l.split("/").length);for(let l of n){let s=S.readFileSync(l,"utf-8").match(/<key>CFBundleIdentifier<\/key>\s*<string>([^<]+)<\/string>/);if(s&&!s[1].includes("$"))return s[1]}let o=Ve(i,[".xcodeproj"]);if(o.length>0){let l=_.join(o[0],"project.pbxproj");if(S.existsSync(l)){let s=S.readFileSync(l,"utf-8").match(/PRODUCT_BUNDLE_IDENTIFIER\s*=\s*"?([^";\s]+)"?;/);if(s)return s[1]}}let r=["app.json","app.config.json","app.config.js","app.config.ts"];for(let l of r)if(S.existsSync(l)){let s=S.readFileSync(l,"utf-8").match(/"bundleIdentifier":\s*"([^"]+)"/);if(s)return s[1]}}}catch{return null}return null},Do=()=>{try{return G("emulator -version",{stdio:"ignore"}),"emulator"}catch{let t=_e.homedir(),i=[_.join(t,"Library/Android/sdk/emulator/emulator"),_.join(t,"Android/Sdk/emulator/emulator"),"/usr/local/lib/android/sdk/emulator/emulator"];for(let n of i)if(S.existsSync(n))return n}return"emulator"},Ro=async(e,t)=>{let i=It();try{if(G("adb devices").toString().split(`
1002
1006
  `).slice(1).map(l=>l.trim()).filter(l=>l.length>0&&!l.startsWith("*")).map(l=>l.split(" ")[0]).length===0){A.warn(h.yellow("No Android devices or emulators found."));let l=Do(),a=[];try{a=G(`${l} -list-avds`).toString().split(`
1003
1007
  `).filter(s=>s.trim().length>0)}catch{}if(a.length>0){let s=await jt({message:"Select an emulator to launch:",options:a.map(u=>({value:u,label:u}))});if(_t(s))return;i.start(`Launching emulator ${s}...`),Ci(l,["-avd",s],{detached:!0,stdio:"ignore"}).unref();let c=0,d=!1;for(;c<60;){try{if(G("adb shell getprop sys.boot_completed",{stdio:"pipe"}).toString().trim()==="1"){d=!0;break}}catch{}await new Promise(u=>setTimeout(u,2e3)),c++}if(!d)throw i.stop("Emulator launch timed out."),new Error("Emulator launch timed out. Please try launching it manually.");i.stop("Emulator launched.")}else throw new Error("No devices found and no emulators available to launch. (Make sure Android SDK is installed)")}i.start("Installing APK on device..."),await Oe("adb",["install","-r",e],process.cwd(),{},t),i.stop("Installation complete.");let r=Te("android");if(r){A.info(h.blue(`\u{1F680} Launching ${r}...`));try{G(`adb shell dumpsys package ${r}`).toString().split(`
1004
- `).find(s=>s.includes("android.intent.action.MAIN")&&s.includes("android.intent.category.LAUNCHER"))?G(`adb shell monkey -p ${r} -c android.intent.category.LAUNCHER 1`,{stdio:"ignore"}):G(`adb shell monkey -p ${r} -c android.intent.category.LAUNCHER 1`,{stdio:"ignore"})}catch{A.warn("Could not auto-launch app. You may need to open it manually.")}}}catch(n){i.stop("Installation failed."),A.error(h.red(`Failed to install APK: ${n.message}`))}},wo=async(e,t,i)=>{let n=It();try{if(!G("xcrun simctl list devices booted").toString().includes("(Booted)")){A.warn(h.yellow("No iOS Simulator is currently booted."));let r=G("xcrun simctl list devices --json").toString(),l=JSON.parse(r).devices,a=[];Object.keys(l).forEach(u=>{l[u].forEach(p=>{p.isAvailable&&a.push({...p,runtime:u})})});let s=await jt({message:"Select a simulator to launch:",options:a.map(u=>({value:u.udid,label:`${u.name} (${u.runtime.split(".").pop()})`}))});if(_t(s))return;n.start(`Booting ${s}...`),G(`xcrun simctl boot ${s}`),G(`open -a Simulator --args -CurrentDeviceUDID ${s}`);let c=0,d=!1;for(;c<30;){try{if(G("xcrun simctl list devices booted").toString().includes(s)){d=!0;break}}catch{}await new Promise(u=>setTimeout(u,2e3)),c++}if(!d)throw n.stop("Simulator boot timed out."),new Error("Simulator boot timed out.");n.stop("Simulator booted.")}n.start("Installing on iOS Simulator..."),await Oe("xcrun",["simctl","install","booted",e],process.cwd(),{},i),n.stop("Installation complete."),A.info(h.blue(`\u{1F680} Launching ${t}...`)),await Oe("xcrun",["simctl","launch","booted",t],process.cwd(),{},i)}catch(o){n.stop("Installation failed."),A.error(h.red(`Failed to install on Simulator: ${o.message}`))}},vo=async(e,t,i)=>{let n=It();n.start("Scanning for connected iOS devices...");try{let o=G("xcrun devicectl list devices --json-output -").toString(),l=(JSON.parse(o).result?.devices||[]).filter(s=>s.connectionProperties?.transportType==="wired"||s.connectionProperties?.transportType==="localNetwork");if(l.length===0)throw n.stop("No connected iOS devices found."),new Error("Please connect your iPhone via USB or ensure it is on the same Wi-Fi for wireless debugging.");let a=l[0].identifier;if(l.length>1){n.stop();let s=await jt({message:"Select a device to install on:",options:l.map(c=>({value:c.identifier,label:`${c.deviceProperties?.name||c.name||c.model?.name} (${c.model?.name||"iPhone"}) - ${c.identifier}`}))});if(_t(s))return;a=s,n.start(`Installing on ${a}...`)}else n.message(`Installing on ${l[0].model.name}...`);await Oe("xcrun",["devicectl","device","install","app","--device",a,e],process.cwd(),{},i),n.stop("Installation complete."),A.info(h.blue(`\u{1F680} Launching ${t}...`)),await Oe("xcrun",["devicectl","device","launch","app","--device",a,t],process.cwd(),{},i)}catch(o){n.stop("Installation failed."),A.error(h.red(`Failed to install on device: ${o.message}`)),A.info(h.dim('Make sure your device is unlocked and "Developer Mode" is enabled in Settings -> Privacy & Security.'))}};import Ti from"fs";import ki from"path";import{isCancel as Kt,log as ke,select as xi,spinner as Oo,text as Co}from"@clack/prompts";import We from"chalk";async function Li(e){let t=await zt(e);t&&(ke.success(We.green(`Maestro run ${t.status||"queued"}: ${t.testRunId}`)),t.launchDeferredReason&&ke.warn(We.yellow(t.launchDeferredReason)),t.dashboardUrl&&ke.info(We.dim("View test run: ")+We.white.underline(t.dashboardUrl)))}async function zt(e){let t=ve(`./${f.configFileName}`),i=e.projectId||t?.projectId,n=e.profile||e.buildProfile||"production";if(!i)return ke.error(`No projectId found. Run \`${f.nameLower} link\` first or pass an internal project id.`),null;let o=e.platform;if(!o&&e.latest){let s=await xi({message:"Select platform for the latest build:",options:[{value:"android",label:"Android"},{value:"ios",label:"iOS"}]});if(Kt(s))return null;o=s}let r=await No(e);if(!r)return null;if(r.kind==="latest"&&!o)return ke.error("Pass --platform when using --latest."),null;if(r.kind==="artifact-url"&&!o)return ke.error("Pass --platform when using --artifact-url."),null;let l=To(e.maestroRetries);if(l===null)return null;let a=Oo();e.quiet||a.start("Queuing Maestro run...");try{let s=await $.post("/tests/maestro",{projectId:i,platform:o,profile:n,latest:r.kind==="latest",buildId:r.kind==="build-id"?r.value:e.buildId,buildUrl:r.kind==="build-url"?r.value:e.buildUrl,artifactUrl:r.kind==="artifact-url"?r.value:e.artifactUrl,flows:e.maestroFlows||".maestro",device:e.maestroDevice||(o==="ios"?"iphone_15":"pixel_6"),retries:l,record:!!e.maestroRecord});if(s.data.status!=="success")throw new Error(s.data.message||"Failed to queue Maestro run");let c=s.data.testRun,d={testRunId:c.testRunId,status:c.status,projectId:i,buildId:c.buildId,platform:c.platform,dashboardUrl:c.dashboardUrl||`${Qe}/tests/${c.testRunId}`,launchDeferredReason:c.launchDeferredReason};return ko(e,d),e.quiet||a.stop("Maestro run queued"),d}catch(s){e.quiet||a.stop("Could not queue Maestro run");let c=s.response?.data?.message||s.message||"Unknown error";return ke.error(We.red(`Maestro queue failed: ${c}`)),null}}async function No(e){if(e.buildId)return{kind:"build-id",value:e.buildId};if(e.buildUrl)return{kind:"build-url",value:e.buildUrl};if(e.artifactUrl)return{kind:"artifact-url",value:e.artifactUrl};if(e.latest)return{kind:"latest"};let t=await xi({message:"Select app artifact source for Maestro:",options:[{value:"latest",label:"Latest successful build"},{value:"build-id",label:"Build ID"},{value:"build-url",label:`${f.name} build URL`},{value:"artifact-url",label:"Direct artifact URL"}]});if(Kt(t))return null;if(t==="latest")return{kind:"latest"};let i=await Co({message:t==="build-id"?"Enter build ID:":t==="build-url"?`Enter ${f.name} build URL:`:"Enter artifact URL:",validate:n=>{let o=String(n||"").trim();if(!o)return"Value is required";if((t==="build-url"||t==="artifact-url")&&!o.startsWith("http"))return"Must be a URL"}});return Kt(i)?null:{kind:t,value:String(i).trim()}}function To(e){if(e==null||e==="")return 1;let t=Number(e);return!Number.isInteger(t)||t<0||t>10?(ke.error("--maestro-retries must be an integer between 0 and 10."),null):t}function ko(e,t){if(!e.jsonOutput)return;let i=ki.resolve(e.jsonOutput),n={...t,updatedAt:new Date().toISOString()};try{let o=ki.dirname(i);o&&o!=="."&&Ti.mkdirSync(o,{recursive:!0}),Ti.writeFileSync(i,JSON.stringify(n,null,2))}catch(o){ke.warn(We.yellow(`Could not write Maestro metadata JSON: ${o.message}`))}}var Pt=async e=>{e.platform!=="android"&&e.platform!=="ios"&&(R.error(`Platform ${e.platform} is not supported. Use 'android' or 'ios'.`),process.exit(1));let t=Vt(),i=e.buildId||xo(),n=e.projectId,o=Date.now(),r=!!n,l=async a=>{if(n)try{await $.patch(`/builds/${n}/${i}`,{status:"failed",error:a})}catch{}};if(e.local&&e.buildId){e.quiet||t.start(`Preparing isolated workspace for build: ${e.buildId}`);try{let a=await $.get(`/builds/${n}/${e.buildId}/source-url`);if(a.data.status!=="success")throw new Error("Failed to get source download URL from API");let s=await rt.get(a.data.downloadUrl,{responseType:"stream"}),c=(n||e.projectId||"default").replace(/[^a-zA-Z0-9-_]/g,"_"),d=ye.join(Lo.homedir(),f.workspacesDir,c);re.mkdirSync(d,{recursive:!0});let u=new Set(["node_modules",`.${f.nameLower}-cache-meta`]),p=new Set(["Pods"]);if(re.existsSync(d)){let B=re.readdirSync(d);for(let w of B){if(u.has(w))continue;if(w==="ios"){let b=ye.join(d,"ios");try{let L=re.readdirSync(b);for(let m of L)if(!p.has(m))try{re.rmSync(ye.join(b,m),{recursive:!0,force:!0})}catch{}}catch{}continue}let U=ye.join(d,w);try{re.rmSync(U,{recursive:!0,force:!0})}catch{}}}let g=ye.join(d,"source.zip"),E=s.data,P=re.createWriteStream(g);await new Promise((B,w)=>{E.pipe(P),E.on("error",U=>w(U)),P.on("finish",()=>B())}),new Hi(g).extractAllTo(d,!0);try{re.unlinkSync(g)}catch{}process.chdir(d),R.info(v.green(`\u2713 Persistent workspace ready: ${d}`)),R.info(v.dim(` \u{1F4E6} Cached dirs preserved: node_modules=${re.existsSync(ye.join(d,"node_modules"))?"\u2705":"\u274C"}, Pods=${re.existsSync(ye.join(d,"ios","Pods"))?"\u2705":"\u274C"}`)),t.stop()}catch(a){t.stop(`Failed to prepare isolated workspace: ${a.message}`),n&&await l(`Setup Error: ${a.message}`),process.exit(1)}}try{let a=e.repo;if(!a)try{a=Fi("git config --get remote.origin.url").toString().trim()}catch{R.warn("Could not detect git repository URL.")}!a&&e.dryRun,a||(a="https://github.com/placeholder/repo.git"),R.info(`Build ID: ${v.cyan(i)}`);let s={},c={},d=ve(`./${f.configFileName}`);if(d){n=d.projectId;let m=e.buildProfile||"production",D=Be(d,m);!D&&e.buildProfile&&(R.error(`Build profile '${m}' not found in ${f.configFileName}`),process.exit(1));let y=D||{};process.env.MACH_DEBUG&&R.info(v.dim(`Build profile: ${m} | Platform: ${e.platform} | Distribution: ${y.distribution||"store"} | Environment: ${y.environment||m}`)),y.env&&(c=y.env,R.info(v.blue(`Use Build Profile: ${m}`)));let I=e.platform,x=y[I]||{},W=["developmentClient","simulator","distribution","buildCommand","apk","iosScheme","preBuild","postBuild","scheme","environment","androidPackage","iosBundleIdentifier","name","iosDeploymentTarget","iosApiKeyId","iosApiKeyIssuer","iosApiKeyPath","iosTeamId","iosConfiguration","iosExportMethod","branch","repo","instanceType","ami","bucket","region","nodeVersion"];e.name=d.name,e.appName=d.name,e.androidPackage=d.android?.package,e.iosBundleIdentifier=d.ios?.bundleIdentifier,e.iosScheme=d.ios?.iosScheme,!e.nodeVersion&&d.nodeVersion&&(e.nodeVersion=d.nodeVersion);let j=M=>M==="androidPackage"?x.androidPackage??x.package??y.androidPackage??y.android?.package:M==="iosBundleIdentifier"?x.iosBundleIdentifier??x.bundleIdentifier??y.iosBundleIdentifier??y.ios?.bundleIdentifier:x[M]!==void 0?x[M]:y[M];for(let M of W){let K=j(M),H=M==="androidPackage"||M==="iosBundleIdentifier";K!==void 0&&(e[M]===void 0||H)&&(e[M]=K)}e.branch=e.branch||"main",e.iosConfiguration=e.iosConfiguration||(e.developmentClient||e.simulator?"Debug":"Release"),e.sshUser=e.sshUser||process.env.USER||"ubuntu",e.simulator===void 0&&(e.simulator=!1),e.local===void 0&&(e.local=!1),e.verbose===void 0&&(e.verbose=!1);let O=M=>{if(!M)return M;if(M.startsWith("scripts.")){let K=M.split(".")[1],H=d.scripts?.[K];if(H)return H;R.warn(`Script reference not found: ${M}`)}return M};e.buildCommand=O(e.buildCommand),e.preBuild=O(e.preBuild),e.postBuild=O(e.postBuild),!e.scheme&&d.scheme&&(e.scheme=d.scheme);let F={...Ke(d,f.envPrefix),...Ke(y,`${f.envPrefix}PROFILE_`)};s={...s,...c,...F},process.env.IOS_P12_PASSWORD&&!s.IOS_P12_PASSWORD&&(s.IOS_P12_PASSWORD=process.env.IOS_P12_PASSWORD),process.env.MATCH_PASSWORD&&!s.MATCH_PASSWORD&&(s.MATCH_PASSWORD=process.env.MATCH_PASSWORD),e.platform==="ios"&&(!e.iosTeamId&&y.ios?.appleTeamId&&(e.iosTeamId=y.ios.appleTeamId),!e.iosTeamId&&d.submit?.[m]?.ios?.appleTeamId&&(e.iosTeamId=d.submit[m].ios.appleTeamId),!e.iosTeamId&&d.submit?.production?.ios?.appleTeamId&&(R.warn(v.yellow(`Check: Using 'production' Team ID for '${m}' build.`)),e.iosTeamId=d.submit.production.ios.appleTeamId),e.iosTeamId?R.info(v.magenta(`\u2713 Injected iOS Team ID from config: ${e.iosTeamId}`)):R.warn(v.yellow("\u26A0\uFE0F No iOS Team ID found. Signing might fail if not managed automatically via Expo.")))}let u="unknown";try{u=Fi("git rev-parse --abbrev-ref HEAD").toString().trim()}catch{R.warn("Failed to detect git branch.")}let p="1.0.0";try{re.existsSync("./package.json")&&(p=JSON.parse(re.readFileSync("./package.json","utf-8")).version||"1.0.0")}catch{}let g=e.buildProfile||"production",E="Internal";e.developmentClient?E="DevelopmentClient":g.toLowerCase().includes("store")||g.toLowerCase()==="production"?E="Store":g.toLowerCase().includes("preview")||g.toLowerCase().includes("staging")?E="Staging":(g.toLowerCase().includes("development")||g.toLowerCase().includes("dev"))&&(E="Development");let P=e.platform==="ios"?"iOS":"Android",C=e.platform==="ios"&&e.simulator?" (Simulator)":"",B=`${P}${C} v${p} (${E})`;if(st(e,{status:"created",projectId:n,buildId:i,platform:e.platform,profile:g,branch:u,version:p,buildType:E,developmentClient:!!e.developmentClient,summary:B}),n){try{let m=e.buildProfile||"production";R.info(v.blue(`Fetching managed secrets for profile: ${m}...`));let D=e.environment||m,I=(await $.get(`/projects/${n}/secrets/export?env=${D}`)).data;I.status==="success"&&I.secrets&&(s={...s,...I.secrets},Object.keys(I.secrets).length>0&&R.info(v.magenta(`\u2713 Injected ${Object.keys(I.secrets).length} secrets from Dashboard.`)))}catch(m){R.warn(`Failed to load managed secrets from Dashboard: ${m.message}`)}try{R.info(v.blue("Fetching managed credentials..."));let m="development";e.distribution==="store"?m="store":e.distribution==="internal"&&(m=e.platform==="ios"?"adhoc":"internal"),e.developmentClient&&(m="development");let D=await $.get("/credentials/resolve",{params:{projectId:n,platform:e.platform,bundleId:e.iosBundleIdentifier||e.androidPackage,distributionType:m}});if(D.data.status==="success"&&D.data.credentials){let y=D.data.credentials;R.info(v.magenta(`\u2713 Found ${y.length} relevant credentials.`));let I=y.filter(O=>{if(O.distributionType){let F=m==="internal"?"adhoc":m;return O.distributionType===F||O.distributionType===m}return!0});R.info(v.dim(` Filtered to ${I.length} credentials for distributionType: ${m}`));let x=!1,W=!1,j=!1;for(let O of I)if(O.downloadUrl)try{let F="",M=5;for(;M>0;)try{let K=await rt.get(O.downloadUrl,{responseType:"arraybuffer",timeout:3e4,headers:{Connection:"close"}});F=Buffer.from(K.data).toString("base64");break}catch(K){if(M--,M===0)throw K;R.warn(v.dim(` - Temporary network error downloading ${O.name}. Retrying... (${5-M}/5)`)),await new Promise(H=>setTimeout(H,2e3))}if(O.type==="ios_cert"&&!x)s.IOS_DIST_P12=F,O.password?(s.IOS_P12_PASSWORD=O.password,R.info(v.dim(` - Injected ${O.name} as IOS_DIST_P12 with password from credential record`))):R.info(v.dim(` - Injected ${O.name} as IOS_DIST_P12`)),x=!0;else if(O.type==="ios_profile"&&!W)s.IOS_PROVISIONING_PROFILE=F,R.info(v.dim(` - Injected ${O.name} as IOS_PROVISIONING_PROFILE`)),W=!0;else if(O.type==="android_keystore"&&!j){s.ANDROID_KEYSTORE_BASE64=F;let K=O.keystorePassword||O.password,H=O.keyPassword||O.keystorePassword||O.password,z=O.alias||O.meta?.alias;if(K)s.ANDROID_STORE_PASSWORD=K,R.info(v.dim(" - Injected keystore password from credential record"));else{let T=["ANDROID_STORE_PASSWORD",...[m==="store"?"PRODUCTION":m==="internal"?"STAGING":"DEVELOPMENT",m.toUpperCase(),"PRODUCTION","STORE","INTERNAL","STAGING","RELEASE","DEBUG"].map(k=>`KEYSTORE_PASSWORD_${k}`),"KEYSTORE_PASSWORD"].find(k=>!!s[k]);T&&s[T]&&(s.ANDROID_STORE_PASSWORD=s[T])}if(H?(s.ANDROID_KEY_PASSWORD=H,R.info(v.dim(" - Injected key password from credential record"))):s.ANDROID_KEY_PASSWORD=s.ANDROID_STORE_PASSWORD||"",z)s.ANDROID_KEY_ALIAS=z;else{let ne=["ANDROID_KEY_ALIAS","KEYSTORE_ALIAS"].find(he=>!!s[he]);ne&&(s.ANDROID_KEY_ALIAS=s[ne])}R.info(v.dim(` - Injected ${O.name} as ANDROID_KEYSTORE_BASE64`)),j=!0}}catch(F){R.warn(`Failed to download credential ${O.name}: ${F.message}`)}}if(e.platform==="android"){let y=e.buildProfile||"production",I=Be(d,y)||{},j=((I.android||{}).versionCode??I.androidVersionCode??d.android?.versionCode??d.expo?.android?.versionCode)==="auto",O=e.autoVersion||j&&e.distribution==="store";if(j&&!O&&R.info(v.dim(` Skipping Google Play versionCode lookup for ${e.distribution||"non-store"} build. Pass --auto-version to force it.`)),O){t.start("Resolving latest versionCode from Google Play...");try{let F=e.androidPackage||d.android?.package||d.expo?.android?.package||d.name,M=(D.data.credentials||[]).find(T=>T.type==="google_service_account"&&(!T.bundleId||T.bundleId===F));if(!M){let k=((await $.get(`/credentials/${n}`)).data.credentials||[]).filter(V=>V.type==="google_service_account");if(M=k.find(V=>V.type==="google_service_account"&&V.bundleId===F),!M&&k.length>0){let V=k.map(N=>N.bundleId).filter(Boolean).join(", ");throw new Error(`Google Service Account not found for package ${F}. Found service credential(s) for: ${V}.`)}}if(!M)throw new Error(`Google Service Account not found for package ${F}. Upload it under this package in Dashboard or run '${f.nameLower} credentials:service --platform android --package-name ${F}'.`);let K=await $.get(`/credentials/${M.credentialId}/download`,{params:{projectId:n}});if(K.data.status!=="success"||!K.data.downloadUrl)throw new Error("Failed to get secure download URL for service account");let z=(await rt.get(K.data.downloadUrl,{headers:{Connection:"close"}})).data,ne=await vi(F,z);if(ne==null)throw new Error("Could not retrieve any version information from Google Play.");let he=ne+1;s.ANDROID_VERSION_CODE=he.toString(),t.stop(`\u2713 Resolved versionCode: ${v.green(he)} (Latest on Play Store: ${ne})`)}catch(F){t.stop("Version resolution failed");let M=F.response?.data?.error?.message||F.message;throw new Error(`Auto-versioning failed: ${M}. Fix Google Play service account permissions or remove android.versionCode="auto".`)}}}if(e.platform==="ios"&&!e.simulator){let y=!!s.IOS_DIST_P12,I=!!s.IOS_PROVISIONING_PROFILE;if(!y||!I){let x=[...y?[]:["Distribution Certificate"],...I?[]:["Provisioning Profile"]].join(" and ");R.error(v.red(`Missing iOS credentials: ${x}`)),e.quiet&&process.exit(1);let W=e.yes||await Ui({message:"Would you like to generate these credentials now?",initialValue:!0});if(W&&!Mi(W))return await et({platform:"ios",profile:g}),e.quiet||R.info(v.green("\u2713 Credentials setup complete! Restarting build phase...")),Pt(e);e.quiet||R.info(v.yellow(`Run \`${f.nameLower} credentials\` to set up signing credentials manually.`)),process.exit(1)}}if(e.platform==="android"&&(e.distribution==="internal"||e.distribution==="store")&&!(!!s.ANDROID_KEYSTORE_BASE64||!!s.ANDROID_KEYSTORE)){R.error(v.red("Missing Android credentials: Signing Keystore")),e.quiet&&process.exit(1);let I=e.yes||await Ui({message:"Would you like to automatically create and upload an Android Keystore for this profile now?",initialValue:!0});if(I&&!Mi(I))return await et({platform:"android",profile:g}),e.quiet||R.info(v.green("\u2713 Android Keystore setup complete! Restarting build phase...")),Pt(e);e.quiet||R.info(v.yellow(`Run \`${f.nameLower} credentials --platform android\` to set up a signing keystore manually.`)),process.exit(1)}}catch(m){R.warn(`Failed to resolve credentials: ${m.message}`)}}let w=!!(e.local&&e.buildId),U=!!(e.local||e.sshHost),b=!U&&!w;if(w){R.info(v.magenta("\u{1F3D7}\uFE0F Runner Mode: Executing isolated build task..."));let m=await Gt({...e,interactive:!1},i,s,n,{branch:u,version:p,summary:B,buildType:E});await L(m),process.exit(0)}async function L(m){if(n&&m.length>0){let D=Vt(),y=[];e.quiet||D.start("Uploading artifacts to Dashboard...");try{for(let I of m){let x=ye.basename(I),W=re.readFileSync(I),j=ye.extname(x).toLowerCase(),O="application/octet-stream",F=await $.post(`/builds/${n}/${i}/artifact-upload-url`,{fileName:x,fileType:O});if(F.data.status!=="success")throw new Error(`Failed to get upload URL for ${x}`);let M=!1;for(let K=1;K<=3;K++)try{await rt.put(F.data.uploadUrl,W,{headers:{"Content-Type":O},maxBodyLength:1/0,maxContentLength:1/0,timeout:12e4}),M=!0;break}catch(H){if(R.warn(v.yellow(`Artifact upload attempt ${K}/3 failed (${H.code||H.message})`)),K<3)await new Promise(z=>setTimeout(z,3e3*K));else throw H}M&&y.push({name:x,url:F.data.downloadUrl,size:W.length,type:j.substring(1)})}e.quiet||D.stop("Artifacts uploaded.")}catch(I){e.quiet||D.stop("Failed to upload artifacts."),R.error(v.red(`Upload error: ${I.message}`));try{await $.patch(`/builds/${n}/${i}`,{status:"completed",artifacts:m.map(x=>ye.basename(x)),endTime:Date.now()})}catch(x){R.warn(v.yellow(`Could not set fallback build status: ${x.message}`))}return}if(n&&y.length>0)try{R.info(v.cyan(`
1008
+ `).find(s=>s.includes("android.intent.action.MAIN")&&s.includes("android.intent.category.LAUNCHER"))?G(`adb shell monkey -p ${r} -c android.intent.category.LAUNCHER 1`,{stdio:"ignore"}):G(`adb shell monkey -p ${r} -c android.intent.category.LAUNCHER 1`,{stdio:"ignore"})}catch{A.warn("Could not auto-launch app. You may need to open it manually.")}}}catch(n){i.stop("Installation failed."),A.error(h.red(`Failed to install APK: ${n.message}`))}},wo=async(e,t,i)=>{let n=It();try{if(!G("xcrun simctl list devices booted").toString().includes("(Booted)")){A.warn(h.yellow("No iOS Simulator is currently booted."));let r=G("xcrun simctl list devices --json").toString(),l=JSON.parse(r).devices,a=[];Object.keys(l).forEach(u=>{l[u].forEach(p=>{p.isAvailable&&a.push({...p,runtime:u})})});let s=await jt({message:"Select a simulator to launch:",options:a.map(u=>({value:u.udid,label:`${u.name} (${u.runtime.split(".").pop()})`}))});if(_t(s))return;n.start(`Booting ${s}...`),G(`xcrun simctl boot ${s}`),G(`open -a Simulator --args -CurrentDeviceUDID ${s}`);let c=0,d=!1;for(;c<30;){try{if(G("xcrun simctl list devices booted").toString().includes(s)){d=!0;break}}catch{}await new Promise(u=>setTimeout(u,2e3)),c++}if(!d)throw n.stop("Simulator boot timed out."),new Error("Simulator boot timed out.");n.stop("Simulator booted.")}n.start("Installing on iOS Simulator..."),await Oe("xcrun",["simctl","install","booted",e],process.cwd(),{},i),n.stop("Installation complete."),A.info(h.blue(`\u{1F680} Launching ${t}...`)),await Oe("xcrun",["simctl","launch","booted",t],process.cwd(),{},i)}catch(o){n.stop("Installation failed."),A.error(h.red(`Failed to install on Simulator: ${o.message}`))}},vo=async(e,t,i)=>{let n=It();n.start("Scanning for connected iOS devices...");try{let o=G("xcrun devicectl list devices --json-output -").toString(),l=(JSON.parse(o).result?.devices||[]).filter(s=>s.connectionProperties?.transportType==="wired"||s.connectionProperties?.transportType==="localNetwork");if(l.length===0)throw n.stop("No connected iOS devices found."),new Error("Please connect your iPhone via USB or ensure it is on the same Wi-Fi for wireless debugging.");let a=l[0].identifier;if(l.length>1){n.stop();let s=await jt({message:"Select a device to install on:",options:l.map(c=>({value:c.identifier,label:`${c.deviceProperties?.name||c.name||c.model?.name} (${c.model?.name||"iPhone"}) - ${c.identifier}`}))});if(_t(s))return;a=s,n.start(`Installing on ${a}...`)}else n.message(`Installing on ${l[0].model.name}...`);await Oe("xcrun",["devicectl","device","install","app","--device",a,e],process.cwd(),{},i),n.stop("Installation complete."),A.info(h.blue(`\u{1F680} Launching ${t}...`)),await Oe("xcrun",["devicectl","device","launch","app","--device",a,t],process.cwd(),{},i)}catch(o){n.stop("Installation failed."),A.error(h.red(`Failed to install on device: ${o.message}`)),A.info(h.dim('Make sure your device is unlocked and "Developer Mode" is enabled in Settings -> Privacy & Security.'))}};import Ti from"fs";import ki from"path";import{isCancel as Kt,log as ke,select as xi,spinner as Oo,text as Co}from"@clack/prompts";import We from"chalk";async function Li(e){let t=await zt(e);t&&(ke.success(We.green(`Maestro run ${t.status||"queued"}: ${t.testRunId}`)),t.launchDeferredReason&&ke.warn(We.yellow(t.launchDeferredReason)),t.dashboardUrl&&ke.info(We.dim("View test run: ")+We.white.underline(t.dashboardUrl)))}async function zt(e){let t=ve(`./${f.configFileName}`),i=e.projectId||t?.projectId,n=e.profile||e.buildProfile||"production";if(!i)return ke.error(`No projectId found. Run \`${f.nameLower} link\` first or pass an internal project id.`),null;let o=e.platform;if(!o&&e.latest){let s=await xi({message:"Select platform for the latest build:",options:[{value:"android",label:"Android"},{value:"ios",label:"iOS"}]});if(Kt(s))return null;o=s}let r=await No(e);if(!r)return null;if(r.kind==="latest"&&!o)return ke.error("Pass --platform when using --latest."),null;if(r.kind==="artifact-url"&&!o)return ke.error("Pass --platform when using --artifact-url."),null;let l=To(e.maestroRetries);if(l===null)return null;let a=Oo();e.quiet||a.start("Queuing Maestro run...");try{let s=await $.post("/tests/maestro",{projectId:i,platform:o,profile:n,latest:r.kind==="latest",buildId:r.kind==="build-id"?r.value:e.buildId,buildUrl:r.kind==="build-url"?r.value:e.buildUrl,artifactUrl:r.kind==="artifact-url"?r.value:e.artifactUrl,flows:e.maestroFlows||".maestro",device:e.maestroDevice||(o==="ios"?"iphone_15":"pixel_6"),retries:l,record:!!e.maestroRecord});if(s.data.status!=="success")throw new Error(s.data.message||"Failed to queue Maestro run");let c=s.data.testRun,d={testRunId:c.testRunId,status:c.status,projectId:i,buildId:c.buildId,platform:c.platform,dashboardUrl:c.dashboardUrl||`${Qe}/tests/${c.testRunId}`,launchDeferredReason:c.launchDeferredReason};return ko(e,d),e.quiet||a.stop("Maestro run queued"),d}catch(s){e.quiet||a.stop("Could not queue Maestro run");let c=s.response?.data?.message||s.message||"Unknown error";return ke.error(We.red(`Maestro queue failed: ${c}`)),null}}async function No(e){if(e.buildId)return{kind:"build-id",value:e.buildId};if(e.buildUrl)return{kind:"build-url",value:e.buildUrl};if(e.artifactUrl)return{kind:"artifact-url",value:e.artifactUrl};if(e.latest)return{kind:"latest"};let t=await xi({message:"Select app artifact source for Maestro:",options:[{value:"latest",label:"Latest successful build"},{value:"build-id",label:"Build ID"},{value:"build-url",label:`${f.name} build URL`},{value:"artifact-url",label:"Direct artifact URL"}]});if(Kt(t))return null;if(t==="latest")return{kind:"latest"};let i=await Co({message:t==="build-id"?"Enter build ID:":t==="build-url"?`Enter ${f.name} build URL:`:"Enter artifact URL:",validate:n=>{let o=String(n||"").trim();if(!o)return"Value is required";if((t==="build-url"||t==="artifact-url")&&!o.startsWith("http"))return"Must be a URL"}});return Kt(i)?null:{kind:t,value:String(i).trim()}}function To(e){if(e==null||e==="")return 1;let t=Number(e);return!Number.isInteger(t)||t<0||t>10?(ke.error("--maestro-retries must be an integer between 0 and 10."),null):t}function ko(e,t){if(!e.jsonOutput)return;let i=ki.resolve(e.jsonOutput),n={...t,updatedAt:new Date().toISOString()};try{let o=ki.dirname(i);o&&o!=="."&&Ti.mkdirSync(o,{recursive:!0}),Ti.writeFileSync(i,JSON.stringify(n,null,2))}catch(o){ke.warn(We.yellow(`Could not write Maestro metadata JSON: ${o.message}`))}}var Pt=async e=>{e.platform!=="android"&&e.platform!=="ios"&&(R.error(`Platform ${e.platform} is not supported. Use 'android' or 'ios'.`),process.exit(1));let t=Vt(),i=e.buildId||xo(),n=e.projectId,o=Date.now(),r=!!n,l=async a=>{if(n)try{await $.patch(`/builds/${n}/${i}`,{status:"failed",error:a})}catch{}};if(e.local&&e.buildId){e.quiet||t.start(`Preparing isolated workspace for build: ${e.buildId}`);try{let a=await $.get(`/builds/${n}/${e.buildId}/source-url`);if(a.data.status!=="success")throw new Error("Failed to get source download URL from API");let s=await rt.get(a.data.downloadUrl,{responseType:"stream"}),c=(n||e.projectId||"default").replace(/[^a-zA-Z0-9-_]/g,"_"),d=ye.join(Lo.homedir(),f.workspacesDir,c);re.mkdirSync(d,{recursive:!0});let u=new Set(["node_modules",`.${f.nameLower}-cache-meta`]),p=new Set(["Pods"]);if(re.existsSync(d)){let B=re.readdirSync(d);for(let w of B){if(u.has(w))continue;if(w==="ios"){let b=ye.join(d,"ios");try{let L=re.readdirSync(b);for(let m of L)if(!p.has(m))try{re.rmSync(ye.join(b,m),{recursive:!0,force:!0})}catch{}}catch{}continue}let U=ye.join(d,w);try{re.rmSync(U,{recursive:!0,force:!0})}catch{}}}let g=ye.join(d,"source.zip"),E=s.data,P=re.createWriteStream(g);await new Promise((B,w)=>{E.pipe(P),E.on("error",U=>w(U)),P.on("finish",()=>B())}),new Hi(g).extractAllTo(d,!0);try{re.unlinkSync(g)}catch{}process.chdir(d),R.info(v.green(`\u2713 Persistent workspace ready: ${d}`)),R.info(v.dim(` \u{1F4E6} Cached dirs preserved: node_modules=${re.existsSync(ye.join(d,"node_modules"))?"\u2705":"\u274C"}, Pods=${re.existsSync(ye.join(d,"ios","Pods"))?"\u2705":"\u274C"}`)),t.stop()}catch(a){t.stop(`Failed to prepare isolated workspace: ${a.message}`),n&&await l(`Setup Error: ${a.message}`),process.exit(1)}}try{let a=e.repo;if(!a)try{a=Fi("git config --get remote.origin.url").toString().trim()}catch{R.warn("Could not detect git repository URL.")}!a&&e.dryRun,a||(a="https://github.com/placeholder/repo.git"),R.info(`Build ID: ${v.cyan(i)}`);let s={},c={},d=ve(`./${f.configFileName}`);if(d){n=d.projectId;let m=e.buildProfile||"production",D=Be(d,m);!D&&e.buildProfile&&(R.error(`Build profile '${m}' not found in ${f.configFileName}`),process.exit(1));let y=D||{};process.env.MACH_DEBUG&&R.info(v.dim(`Build profile: ${m} | Platform: ${e.platform} | Distribution: ${y.distribution||"store"} | Environment: ${y.environment||m}`)),y.env&&(c=y.env,R.info(v.blue(`Use Build Profile: ${m}`)));let I=e.platform,x=y[I]||{},W=["developmentClient","simulator","distribution","buildCommand","apk","iosScheme","preBuild","postBuild","scheme","environment","androidPackage","iosBundleIdentifier","name","iosDeploymentTarget","iosApiKeyId","iosApiKeyIssuer","iosApiKeyPath","iosTeamId","iosConfiguration","iosExportMethod","branch","repo","instanceType","ami","bucket","region","nodeVersion"];e.name=d.name,e.appName=d.name,e.androidPackage=d.android?.package,e.iosBundleIdentifier=d.ios?.bundleIdentifier,e.iosScheme=d.ios?.iosScheme,!e.nodeVersion&&d.nodeVersion&&(e.nodeVersion=d.nodeVersion);let j=M=>M==="androidPackage"?x.androidPackage??x.package??y.androidPackage??y.android?.package:M==="iosBundleIdentifier"?x.iosBundleIdentifier??x.bundleIdentifier??y.iosBundleIdentifier??y.ios?.bundleIdentifier:x[M]!==void 0?x[M]:y[M];for(let M of W){let K=j(M),H=M==="androidPackage"||M==="iosBundleIdentifier";K!==void 0&&(e[M]===void 0||H)&&(e[M]=K)}e.branch=e.branch||"main",e.iosConfiguration=e.iosConfiguration||(e.developmentClient||e.simulator?"Debug":"Release"),e.sshUser=e.sshUser||process.env.USER||"ubuntu",e.simulator===void 0&&(e.simulator=!1),e.local===void 0&&(e.local=!1),e.verbose===void 0&&(e.verbose=!1);let O=M=>{if(!M)return M;if(M.startsWith("scripts.")){let K=M.split(".")[1],H=d.scripts?.[K];if(H)return H;R.warn(`Script reference not found: ${M}`)}return M};e.buildCommand=O(e.buildCommand),e.preBuild=O(e.preBuild),e.postBuild=O(e.postBuild),!e.scheme&&d.scheme&&(e.scheme=d.scheme);let F={...Ke(d,f.envPrefix),...Ke(y,`${f.envPrefix}PROFILE_`)};s={...s,...c,...F},process.env.IOS_P12_PASSWORD&&!s.IOS_P12_PASSWORD&&(s.IOS_P12_PASSWORD=process.env.IOS_P12_PASSWORD),process.env.MATCH_PASSWORD&&!s.MATCH_PASSWORD&&(s.MATCH_PASSWORD=process.env.MATCH_PASSWORD),e.platform==="ios"&&(!e.iosTeamId&&y.ios?.appleTeamId&&(e.iosTeamId=y.ios.appleTeamId),!e.iosTeamId&&d.submit?.[m]?.ios?.appleTeamId&&(e.iosTeamId=d.submit[m].ios.appleTeamId),!e.iosTeamId&&d.submit?.production?.ios?.appleTeamId&&(R.warn(v.yellow(`Check: Using 'production' Team ID for '${m}' build.`)),e.iosTeamId=d.submit.production.ios.appleTeamId),e.iosTeamId?R.info(v.magenta(`\u2713 Injected iOS Team ID from config: ${e.iosTeamId}`)):R.warn(v.yellow("\u26A0\uFE0F No iOS Team ID found. Signing might fail if not managed automatically via Expo.")))}let u="unknown";try{u=Fi("git rev-parse --abbrev-ref HEAD").toString().trim()}catch{R.warn("Failed to detect git branch.")}let p="1.0.0";try{re.existsSync("./package.json")&&(p=JSON.parse(re.readFileSync("./package.json","utf-8")).version||"1.0.0")}catch{}let g=e.buildProfile||"production",E="Internal";e.developmentClient?E="DevelopmentClient":g.toLowerCase().includes("store")||g.toLowerCase()==="production"?E="Store":g.toLowerCase().includes("preview")||g.toLowerCase().includes("staging")?E="Staging":(g.toLowerCase().includes("development")||g.toLowerCase().includes("dev"))&&(E="Development");let P=e.platform==="ios"?"iOS":"Android",C=e.platform==="ios"&&e.simulator?" (Simulator)":"",B=`${P}${C} v${p} (${E})`;if(st(e,{status:"created",projectId:n,buildId:i,platform:e.platform,profile:g,branch:u,version:p,buildType:E,developmentClient:!!e.developmentClient,summary:B}),n){try{let m=e.buildProfile||"production";R.info(v.blue(`Fetching managed secrets for profile: ${m}...`));let D=e.environment||m,I=(await $.get(`/projects/${n}/secrets/export?env=${D}`)).data;I.status==="success"&&I.secrets&&(s={...s,...I.secrets},Object.keys(I.secrets).length>0&&R.info(v.magenta(`\u2713 Injected ${Object.keys(I.secrets).length} secrets from Dashboard.`)))}catch(m){R.warn(`Failed to load managed secrets from Dashboard: ${m.message}`)}try{R.info(v.blue("Fetching managed credentials..."));let m="development";e.distribution==="store"?m="store":e.distribution==="internal"&&(m=e.platform==="ios"?"adhoc":"internal"),e.developmentClient&&(m="development");let D=await $.get("/credentials/resolve",{params:{projectId:n,platform:e.platform,bundleId:e.iosBundleIdentifier||e.androidPackage,distributionType:m}});if(D.data.status==="success"&&D.data.credentials){let y=D.data.credentials;R.info(v.magenta(`\u2713 Found ${y.length} relevant credentials.`));let I=y.filter(O=>{if(O.distributionType){let F=m==="internal"?"adhoc":m;return O.distributionType===F||O.distributionType===m}return!0});R.info(v.dim(` Filtered to ${I.length} credentials for distributionType: ${m}`));let x=!1,W=!1,j=!1;for(let O of I)if(O.downloadUrl)try{let F="",M=5;for(;M>0;)try{let K=await rt.get(O.downloadUrl,{responseType:"arraybuffer",timeout:3e4,headers:{Connection:"close"}});F=Buffer.from(K.data).toString("base64");break}catch(K){if(M--,M===0)throw K;R.warn(v.dim(` - Temporary network error downloading ${O.name}. Retrying... (${5-M}/5)`)),await new Promise(H=>setTimeout(H,2e3))}if(O.type==="ios_cert"&&!x)s.IOS_DIST_P12=F,O.password?(s.IOS_P12_PASSWORD=O.password,R.info(v.dim(` - Injected ${O.name} as IOS_DIST_P12 with password from credential record`))):R.info(v.dim(` - Injected ${O.name} as IOS_DIST_P12`)),x=!0;else if(O.type==="ios_profile"&&!W)s.IOS_PROVISIONING_PROFILE=F,R.info(v.dim(` - Injected ${O.name} as IOS_PROVISIONING_PROFILE`)),W=!0;else if(O.type==="android_keystore"&&!j){s.ANDROID_KEYSTORE_BASE64=F;let K=O.keystorePassword||O.password,H=O.keyPassword||O.keystorePassword||O.password,z=O.alias||O.meta?.alias;if(K)s.ANDROID_STORE_PASSWORD=K,R.info(v.dim(" - Injected keystore password from credential record"));else{let T=["ANDROID_STORE_PASSWORD",...[m==="store"?"PRODUCTION":m==="internal"?"STAGING":"DEVELOPMENT",m.toUpperCase(),"PRODUCTION","STORE","INTERNAL","STAGING","RELEASE","DEBUG"].map(k=>`KEYSTORE_PASSWORD_${k}`),"KEYSTORE_PASSWORD"].find(k=>!!s[k]);T&&s[T]&&(s.ANDROID_STORE_PASSWORD=s[T])}if(H?(s.ANDROID_KEY_PASSWORD=H,R.info(v.dim(" - Injected key password from credential record"))):s.ANDROID_KEY_PASSWORD=s.ANDROID_STORE_PASSWORD||"",z)s.ANDROID_KEY_ALIAS=z;else{let ne=["ANDROID_KEY_ALIAS","KEYSTORE_ALIAS"].find(he=>!!s[he]);ne&&(s.ANDROID_KEY_ALIAS=s[ne])}R.info(v.dim(` - Injected ${O.name} as ANDROID_KEYSTORE_BASE64`)),j=!0}}catch(F){R.warn(`Failed to download credential ${O.name}: ${F.message}`)}}if(e.platform==="android"){let y=e.buildProfile||"production",I=Be(d,y)||{},j=((I.android||{}).versionCode??I.androidVersionCode??d.android?.versionCode??d.expo?.android?.versionCode)==="auto",O=e.autoVersion||j&&e.distribution==="store";if(j&&!O&&R.info(v.dim(` Skipping Google Play versionCode lookup for ${e.distribution||"non-store"} build. Pass --auto-version to force it.`)),O){t.start("Resolving latest versionCode from Google Play...");try{let F=e.androidPackage||d.android?.package||d.expo?.android?.package||d.name,M=(D.data.credentials||[]).find(T=>T.type==="google_service_account"&&(!T.bundleId||T.bundleId===F));if(!M){let k=((await $.get(`/credentials/${n}`)).data.credentials||[]).filter(V=>V.type==="google_service_account");if(M=k.find(V=>V.type==="google_service_account"&&V.bundleId===F),!M&&k.length>0){let V=k.map(N=>N.bundleId).filter(Boolean).join(", ");throw new Error(`Google Service Account not found for package ${F}. Found service credential(s) for: ${V}.`)}}if(!M)throw new Error(`Google Service Account not found for package ${F}. Upload it under this package in Dashboard or run '${f.nameLower} credentials:service --platform android --package-name ${F}'.`);let K=await $.get(`/credentials/${M.credentialId}/download`,{params:{projectId:n}});if(K.data.status!=="success"||!K.data.downloadUrl)throw new Error("Failed to get secure download URL for service account");let z=(await rt.get(K.data.downloadUrl,{headers:{Connection:"close"}})).data,ne=await vi(F,z);if(ne==null)throw new Error("Could not retrieve any version information from Google Play.");let he=ne+1;s.ANDROID_VERSION_CODE=he.toString(),t.stop(`\u2713 Resolved versionCode: ${v.green(he)} (Latest on Play Store: ${ne})`)}catch(F){t.stop("Version resolution failed");let M=F.response?.data?.error?.message||F.message;throw new Error(`Auto-versioning failed: ${M}. Fix Google Play service account permissions or remove android.versionCode="auto".`)}}}if(e.platform==="ios"&&!e.simulator){let y=!!s.IOS_DIST_P12,I=!!s.IOS_PROVISIONING_PROFILE;if(!y||!I){let x=[...y?[]:["Distribution Certificate"],...I?[]:["Provisioning Profile"]].join(" and ");R.error(v.red(`Missing iOS credentials: ${x}`)),e.quiet&&process.exit(1);let W=e.yes||await Ui({message:"Would you like to generate these credentials now?",initialValue:!0});if(W&&!Mi(W))return await et({platform:"ios",profile:g}),e.quiet||R.info(v.green("\u2713 Credentials setup complete! Restarting build phase...")),Pt(e);e.quiet||R.info(v.yellow(`Run \`${f.nameLower} credentials\` to set up signing credentials manually.`)),process.exit(1)}}if(e.platform==="android"&&!e.developmentClient&&(e.distribution==="internal"||e.distribution==="store")&&!(!!s.ANDROID_KEYSTORE_BASE64||!!s.ANDROID_KEYSTORE)){R.error(v.red("Missing Android credentials: Signing Keystore")),e.quiet&&process.exit(1);let I=e.yes||await Ui({message:"Would you like to automatically create and upload an Android Keystore for this profile now?",initialValue:!0});if(I&&!Mi(I))return await et({platform:"android",profile:g}),e.quiet||R.info(v.green("\u2713 Android Keystore setup complete! Restarting build phase...")),Pt(e);e.quiet||R.info(v.yellow(`Run \`${f.nameLower} credentials --platform android\` to set up a signing keystore manually.`)),process.exit(1)}}catch(m){R.warn(`Failed to resolve credentials: ${m.message}`)}}let w=!!(e.local&&e.buildId),U=!!(e.local||e.sshHost),b=!U&&!w;if(w){R.info(v.magenta("\u{1F3D7}\uFE0F Runner Mode: Executing isolated build task..."));let m=await Gt({...e,interactive:!1},i,s,n,{branch:u,version:p,summary:B,buildType:E});await L(m),process.exit(0)}async function L(m){if(n&&m.length>0){let D=Vt(),y=[];e.quiet||D.start("Uploading artifacts to Dashboard...");try{for(let I of m){let x=ye.basename(I),W=re.readFileSync(I),j=ye.extname(x).toLowerCase(),O="application/octet-stream",F=await $.post(`/builds/${n}/${i}/artifact-upload-url`,{fileName:x,fileType:O});if(F.data.status!=="success")throw new Error(`Failed to get upload URL for ${x}`);let M=!1;for(let K=1;K<=3;K++)try{await rt.put(F.data.uploadUrl,W,{headers:{"Content-Type":O},maxBodyLength:1/0,maxContentLength:1/0,timeout:12e4}),M=!0;break}catch(H){if(R.warn(v.yellow(`Artifact upload attempt ${K}/3 failed (${H.code||H.message})`)),K<3)await new Promise(z=>setTimeout(z,3e3*K));else throw H}M&&y.push({name:x,url:F.data.downloadUrl,size:W.length,type:j.substring(1)})}e.quiet||D.stop("Artifacts uploaded.")}catch(I){e.quiet||D.stop("Failed to upload artifacts."),R.error(v.red(`Upload error: ${I.message}`));try{await $.patch(`/builds/${n}/${i}`,{status:"completed",artifacts:m.map(x=>ye.basename(x)),endTime:Date.now()})}catch(x){R.warn(v.yellow(`Could not set fallback build status: ${x.message}`))}return}if(n&&y.length>0)try{R.info(v.cyan(`
1005
1009
  \u{1F517} Download Links:`));for(let I of y)R.info(v.dim(` - ${I.name}: `)+v.blue.underline(I.url));await $.patch(`/builds/${n}/${i}`,{status:"success",artifacts:y,endTime:Date.now()}),st(e,{status:"success",projectId:n,buildId:i,platform:e.platform,profile:g,branch:u,version:p,buildType:E,developmentClient:!!e.developmentClient,summary:B,artifacts:y}),R.success(v.green(`
1006
1010
  \u2713 Build completed and reported to dashboard.`)),e.maestro&&!w&&await Bi(n,i,e,g)}catch(I){R.warn(v.yellow(`
1007
1011
  \u26A0\uFE0F Could not report to dashboard: ${I.message}`))}}else if(n)try{await $.patch(`/builds/${n}/${i}`,{status:"completed",endTime:Date.now()}),st(e,{status:"completed",projectId:n,buildId:i,platform:e.platform,profile:g,branch:u,version:p,buildType:E,developmentClient:!!e.developmentClient,summary:B})}catch{}}if(U){if(R.info(v.cyan(`\u{1F680} Direct Build Mode: Executing on ${e.sshHost||"local"}...`)),n&&!r){let m=process.argv.slice(3).join(" ");await $.post("/builds",{projectId:n,buildId:i,platform:e.platform,status:"building",branch:u,version:p,summary:B,startTime:o,buildType:E,buildProfile:g,buildArgs:m,simulator:!!e.simulator,developmentClient:!!e.developmentClient})}if(e.sshHost&&e.platform==="ios"){let m=await wi(e,i,s,n)}else{let m=await Gt({...e,interactive:!!e.local},i,s,n,{branch:u,version:p,summary:B,buildType:E});await L(m)}return}if(b&&(R.info(v.blue("\u{1F6F0}\uFE0F Cloud Initiator Mode: Preparing orchestration...")),!e.dryRun)){e.quiet||t.start("Zipping and uploading local source...");let m=await $.post("/builds/source-upload-url",{projectId:n,buildId:i});if(m.data.status!=="success")throw t.stop("Failed to get upload URL."),new Error("Failed to get source upload URL from API");let D=new Hi,y=re.readdirSync("."),I=["node_modules",".git","dist","build","builds",".gradle",".idea","android/build","ios/build","ios/Pods",`.${f.nameLower}_cli`];for(let j of y){if(I.includes(j))continue;re.statSync(j).isDirectory()?D.addLocalFolder(j,j):D.addLocalFile(j)}let x=D.toBuffer();e.quiet||t.message(`Uploading source (${(x.length/1024/1024).toFixed(1)} MB)...`);let W=!1;for(let j=1;j<=3;j++)try{await rt.put(m.data.uploadUrl,x,{headers:{"Content-Type":"application/zip"},maxBodyLength:1/0,maxContentLength:1/0,timeout:12e4}),W=!0;break}catch(O){if(j<3)t.message(`Upload attempt ${j} failed (${O.code||O.message}), retrying...`),await new Promise(F=>setTimeout(F,2e3*j));else throw O}if(e.quiet||t.stop("Source uploaded"),n){let j=process.argv.slice(3).join(" ");await $.post("/builds",{projectId:n,buildId:i,platform:e.platform,status:"pending",branch:u,version:p,summary:B,startTime:o,buildType:E,buildProfile:g,buildArgs:j,simulator:!!e.simulator,developmentClient:!!e.developmentClient}),R.info(v.green("\u2713 Cloud build registered."))}e.platform==="android"&&await Di(e,i,s,n,e.preBuild),e.quiet||R.info(v.cyan("\u{1F4E1} Connecting to build stream...")),await Uo(n,i,e),e.maestro&&await Bi(n,i,e,g);return}}catch(a){let s=a.message||"Build failed";a.response?.data?.message?s=a.response.data.message:a.message.includes("status code 402")?s="Insufficient wallet balance. Please add credits in the Dashboard.":a.message.includes("status code 403")&&(s="Monthly build quota exceeded. Upgrade your plan in the Dashboard."),n&&!e.local&&await l(s),R.error(v.red(`\u2717 Build failed: ${s}`)),process.exit(1)}};async function Bi(e,t,i,n){R.info(v.cyan(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radhya/mach",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "description": "Mach CLI: Cloud Build Orchestrator for React Native & Expo",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",