[{"data":1,"prerenderedAt":704},["ShallowReactive",2],{"docs-page:en:\u002Fdocs\u002Fdeploy\u002Fpublish-release":3,"docs-navigation:en":606},{"id":4,"title":5,"body":6,"description":598,"extension":599,"meta":600,"navigation":601,"path":602,"seo":603,"stem":604,"__hash__":605},"docs_en\u002Fen\u002Fdocs\u002Fdeploy\u002Fpublish-release.md","Publish a release",{"type":7,"value":8,"toc":570},"minimark",[9,13,16,19,33,38,41,91,95,100,103,106,110,116,119,122,125,128,131,134,151,154,158,161,164,168,171,175,184,187,191,202,205,209,212,216,219,230,233,237,240,244,247,251,258,262,265,280,283,287,290,297,323,326,329,333,336,343,364,370,373,379,400,403,407,410,440,443,447,450,453,472,475,486,489,496,502,506,509,543,567],[10,11,12],"p",{},"Publishing in Otalan means creating one release for one exact tuple and asking Otalan to validate the uploaded archive before activation.",[10,14,15],{},"On Otalan Cloud, validation is handled by Otalan.",[10,17,18],{},"The dashboard is designed for the first operational phase of a product: a release engineer or product engineer can publish deliberately, inspect the result, and roll back quickly if needed.",[10,20,21,22,27,28,32],{},"Use this page when you are operating the dashboard publish form. For the first end-to-end release path, start with ",[23,24,26],"a",{"href":25},"\u002Fdocs\u002Fquick-start\u002Fquick-start","Publish in 5 minutes",". For CI automation, use ",[23,29,31],{"href":30},"\u002Fdocs\u002Ftooling\u002Fcli","CLI",".",[34,35,37],"h2",{"id":36},"before-you-publish","Before you publish",[10,39,40],{},"Make sure all of the following are already true:",[42,43,44,48,56,64,71,88],"ul",{},[45,46,47],"li",{},"you selected the correct organization and project",[45,49,50,51,55],{},"the target app is registered and active on the ",[52,53,54],"strong",{},"Apps"," page",[45,57,58,59,63],{},"you ran ",[60,61,62],"code",{},"otalan bundle"," in the app repository",[45,65,66,67,70],{},"the generated ",[60,68,69],{},".otalan\u002Fbundle\u002Fbundle-\u003Cbundle-id>.zip"," file is ready for dashboard upload",[45,72,73,74,77,78,77,81,84,85],{},"you know whether this publish is for Capacitor or Expo, plus the target ",[60,75,76],{},"platform",", ",[60,79,80],{},"channel",[60,82,83],{},"runtimeVersion",", and ",[60,86,87],{},"bundleId",[45,89,90],{},"no product images, videos, large documents, or other externally hosted media are embedded in the bundle",[34,92,94],{"id":93},"field-by-field-guide","Field-by-field guide",[96,97,99],"h3",{"id":98},"app","App",[10,101,102],{},"Choose the registered app that owns the release. App registration is project-scoped, so the publish form only lists apps for the selected project.",[10,104,105],{},"Archived apps are not valid publish targets until restored.",[96,107,109],{"id":108},"app-runtime","App runtime",[10,111,112,113,32],{},"After selecting the app, choose whether this release is for a Capacitor app or an Expo app using ",[60,114,115],{},"expo-updates",[10,117,118],{},"This choice controls the publish form. Expo releases must attach the generated Otalan manifest JSON for validation. Capacitor releases do not show that field.",[10,120,121],{},"The runtime choice does not block older versions by version number. Other runtimes and older Expo or Capacitor versions might work or might not, but they are not supported for the moment.",[96,123,124],{"id":76},"Platform",[10,126,127],{},"Choose the client platform that should receive the bundle. Keep iOS and Android releases separate even if the web code is similar.",[96,129,130],{"id":80},"Channel",[10,132,133],{},"Use the channel to separate audience slices such as:",[42,135,136,141,146],{},[45,137,138],{},[60,139,140],{},"production",[45,142,143],{},[60,144,145],{},"beta",[45,147,148],{},[60,149,150],{},"internal",[10,152,153],{},"Channels are independent release lines.",[96,155,157],{"id":156},"runtime-version","Runtime version",[10,159,160],{},"This is the compatibility boundary. A client only receives bundles that match the exact runtime version line it reports.",[10,162,163],{},"For Capacitor, this is the installed runtime version. For Expo, this field maps to the runtime version used for compatibility.",[96,165,167],{"id":166},"bundle-id","Bundle ID",[10,169,170],{},"This is the identifier for the individual web release. It should be unique for the target tuple and understandable to operators scanning the bundle history later.",[96,172,174],{"id":173},"zip-archive","ZIP archive",[10,176,177,178,180,181,183],{},"When publishing from the dashboard UI, upload the ",[60,179,69],{}," file generated by ",[60,182,62],{},". The archive is validated before activation.",[10,185,186],{},"Keep this ZIP minimal. Content-heavy media should live behind your external hosting and be referenced by URL, not embedded in JavaScript, CSS, base64 strings, or the release ZIP.",[96,188,190],{"id":189},"expo-manifest-json","Expo manifest JSON",[10,192,193,194,197,198,201],{},"This field is required after choosing the Expo runtime. Paste the generated Otalan ",[60,195,196],{},".otalan\u002Fbundle\u002Fmanifest.json"," content, or drop the ",[60,199,200],{},"manifest.json"," file directly onto the field so Otalan can validate the Expo release metadata.",[10,203,204],{},"Otalan uses the generated manifest to serve Expo clients correctly.",[96,206,208],{"id":207},"mandatory-update","Mandatory update",[10,210,211],{},"Use this flag when the client should treat the update as mandatory according to the runtime behavior implemented on your side.",[96,213,215],{"id":214},"rollout-percent","Rollout percent",[10,217,218],{},"Use rollout to limit exposure:",[42,220,221,227],{},[45,222,223,226],{},[60,224,225],{},"100"," means full rollout",[45,228,229],{},"smaller values create a staged rollout",[10,231,232],{},"Partial rollout cohorts are seeded by bundle ID and stable device identifier, so each bundle gets its own deterministic cohort. Partial rollout works best when the client sends the same stable device identifier on every update check.",[96,234,236],{"id":235},"release-notes","Release notes",[10,238,239],{},"This is optional, but it is useful for auditability and operator context. Good release notes make future rollback decisions easier.",[34,241,243],{"id":242},"what-happens-after-you-submit","What happens after you submit",[10,245,246],{},"The publish flow has two phases:",[96,248,250],{"id":249},"phase-1-upload","Phase 1: Upload",[10,252,253,254,257],{},"The dashboard and ",[60,255,256],{},"otalan publish"," handle upload details automatically.",[96,259,261],{"id":260},"phase-2-validation-and-activation","Phase 2: Validation and activation",[10,263,264],{},"Otalan then:",[266,267,268,271,274,277],"ol",{},[45,269,270],{},"validates the archive",[45,272,273],{},"rejects unsafe or invalid content if necessary",[45,275,276],{},"for Expo releases, validates the generated Expo metadata",[45,278,279],{},"activates the release for the selected tuple when validation succeeds",[10,281,282],{},"Storage shown in the dashboard is the stored release footprint, not only the uploaded ZIP. Capacitor releases count the promoted archive. Expo releases count the promoted archive plus the extracted launch asset and listed asset objects persisted from the generated manifest.",[34,284,286],{"id":285},"publish-statuses","Publish statuses",[10,288,289],{},"The dashboard reports publish status so operators can see whether they should wait, retry, or investigate. The Publish page shows ongoing publishes and recent failures, including the stored failure reason. While validation is still active, the Bundles and Rollback pages also show the submitted bundle as verification in progress.",[10,291,292,293,296],{},"Use ",[52,294,295],{},"Clear"," on the Publish page to remove failed activity entries after cleanup is finished. Active validations stay visible until they succeed or fail.",[42,298,299,305,311,317],{},[45,300,301,304],{},[60,302,303],{},"pending",": the publish is waiting for validation",[45,306,307,310],{},[60,308,309],{},"processing",": Otalan is validating the archive",[45,312,313,316],{},[60,314,315],{},"ready",": validation succeeded and the release is active",[45,318,319,322],{},[60,320,321],{},"failed",": validation failed and the release was not activated",[10,324,325],{},"If validation fails, the previously active bundle remains unchanged.",[10,327,328],{},"For Expo releases, the generated manifest tells Expo where to fetch the active release assets.",[34,330,332],{"id":331},"verify-the-release-in-the-app","Verify the release in the app",[10,334,335],{},"Publishing makes the bundle active on the Otalan side. The installed app still has to perform an update check before it can receive the new release.",[10,337,338,339,342],{},"For Capacitor clients, trigger whatever path in your app calls ",[60,340,341],{},"POST \u002Fcapacitor\u002Fcheck",". In many apps that means fully closing and reopening the app, because the update check runs on startup. If your app exposes a manual \"check for update\" action or a development trigger, use that instead.",[10,344,345,346,349,350,353,354,77,357,77,359,84,361,363],{},"When ",[60,347,348],{},"updateAvailable"," is ",[60,351,352],{},"true",", the response includes the matched ",[60,355,356],{},"appId",[60,358,76],{},[60,360,80],{},[60,362,83],{}," alongside the bundle details.",[10,365,366,367,369],{},"For Expo clients, trigger the app flow that asks ",[60,368,115],{}," to check the Otalan updates endpoint.",[10,371,372],{},"Before widening a rollout, run the complete update path in a local or staging environment and rehearse rollback to a known-good bundle for the same tuple. Otalan can validate and activate the archive, but it cannot prove your app-specific startup, plugin, data migration, or third-party runtime behavior is safe.",[10,374,375,376,378],{},"If the app does not receive the new bundle after the publish status is ",[60,377,315],{},", verify these values before rebuilding the native app:",[42,380,381,385,389,393,397],{},[45,382,383],{},[60,384,356],{},[45,386,387],{},[60,388,76],{},[45,390,391],{},[60,392,80],{},[45,394,395],{},[60,396,83],{},[45,398,399],{},"rollout percent and device assignment",[10,401,402],{},"You only need a new native build when the change depends on native code, native plugins, permissions, or a different runtime version.",[34,404,406],{"id":405},"production-verification","Production verification",[10,408,409],{},"Before widening a production rollout, verify the full client path:",[42,411,412,415,418,421,424,437],{},[45,413,414],{},"update A received by one real iOS device",[45,416,417],{},"update A received by iOS and Android simulators",[45,419,420],{},"update B received by the same device and simulators, proving clients are not stuck on the first bundle",[45,422,423],{},"rollback to the previous known-good bundle received by the same device and simulators",[45,425,426,427,77,429,77,431,77,433,84,435],{},"matching tuple values recorded for every check: ",[60,428,356],{},[60,430,76],{},[60,432,80],{},[60,434,83],{},[60,436,87],{},[45,438,439],{},"status confirmed in Otalan after each publish or rollback",[10,441,442],{},"Keep the release artifact small and keep verification notes free of API keys, project secrets, and customer data.",[34,444,446],{"id":445},"rollout-and-rollback-guidance","Rollout and rollback guidance",[10,448,449],{},"Use staged rollout whenever the change has meaningful risk.",[10,451,452],{},"Examples:",[42,454,455,461,467],{},[45,456,457,460],{},[60,458,459],{},"10"," for a canary release",[45,462,463,466],{},[60,464,465],{},"25"," for a wider initial deployment",[45,468,469,471],{},[60,470,225],{}," for a full release after confidence is established",[10,473,474],{},"If a release misbehaves, you can:",[42,476,477,480,483],{},[45,478,479],{},"pause the rollout",[45,481,482],{},"resume it later",[45,484,485],{},"roll back to a previously published bundle for the same tuple",[10,487,488],{},"Rollback is only safe within the same exact compatibility tuple. That is a feature, not a limitation.",[10,490,491,492,495],{},"Rollback can only reactivate a bundle that already exists in Otalan. If the target version is not listed on the ",[52,493,494],{},"Bundles"," page for that tuple, it was not registered there and cannot be used as a rollback target.",[10,497,498,499,501],{},"The ",[52,500,494],{}," page shows the original published timestamp for each bundle. Rollback keeps that displayed timestamp unchanged.",[34,503,505],{"id":504},"recommended-manual-validation-loop","Recommended manual validation loop",[10,507,508],{},"For an operator-driven release, a practical checklist is:",[266,510,511,514,523,528,531,534,537,540],{},[45,512,513],{},"confirm the tuple values",[45,515,516,517,519,520,522],{},"run ",[60,518,62],{}," and upload ",[60,521,69],{}," through the dashboard",[45,524,525,526],{},"watch the publish status until it reaches ",[60,527,315],{},[45,529,530],{},"verify the bundle appears in the bundle inventory, using the runtime type filter to view Expo and Capacitor releases separately when needed",[45,532,533],{},"restart the app or trigger its manual update check",[45,535,536],{},"verify the client receives the expected release",[45,538,539],{},"rehearse rollback to a known-good bundle for the same tuple",[45,541,542],{},"increase rollout if you started with a staged percentage",[10,544,545,546,549,550,553,554,557,558,77,561,84,564,32],{},"The bundle inventory channel filter accepts glob-style ",[60,547,548],{},"*"," and ",[60,551,552],{},"?"," patterns. For example, ",[60,555,556],{},"ota*"," includes channels such as ",[60,559,560],{},"ota",[60,562,563],{},"ota-beta",[60,565,566],{},"ota-production",[10,568,569],{},"That loop is fast enough for early-stage operations and strict enough to catch most mistakes before a release reaches the full target audience.",{"title":571,"searchDepth":572,"depth":572,"links":573},"",3,[574,576,589,593,594,595,596,597],{"id":36,"depth":575,"text":37},2,{"id":93,"depth":575,"text":94,"children":577},[578,579,580,581,582,583,584,585,586,587,588],{"id":98,"depth":572,"text":99},{"id":108,"depth":572,"text":109},{"id":76,"depth":572,"text":124},{"id":80,"depth":572,"text":130},{"id":156,"depth":572,"text":157},{"id":166,"depth":572,"text":167},{"id":173,"depth":572,"text":174},{"id":189,"depth":572,"text":190},{"id":207,"depth":572,"text":208},{"id":214,"depth":572,"text":215},{"id":235,"depth":572,"text":236},{"id":242,"depth":575,"text":243,"children":590},[591,592],{"id":249,"depth":572,"text":250},{"id":260,"depth":572,"text":261},{"id":285,"depth":575,"text":286},{"id":331,"depth":575,"text":332},{"id":405,"depth":575,"text":406},{"id":445,"depth":575,"text":446},{"id":504,"depth":575,"text":505},"Submit a release through the dashboard, understand each field in the publish form, and operate the validation lifecycle with confidence.","md",{},true,"\u002Fen\u002Fdocs\u002Fdeploy\u002Fpublish-release",{"title":5,"description":598},"en\u002Fdocs\u002Fdeploy\u002Fpublish-release","U07RgHpTTw1AHjYRTy6w8Rg5-GHfgGJcs2lYBiydT0c",[607],{"title":608,"path":609,"stem":610,"children":611,"page":629},"En","\u002Fen","en",[612],{"title":613,"path":614,"stem":615,"children":616,"page":-1,"description":618},"Introduction","\u002Fen\u002Fdocs","en\u002Fdocs\u002Findex",[617,619,630,640,646,656,675,694],{"title":613,"path":614,"stem":615,"description":618},"Understand what Otalan is, when to use it, and how the first safe OTA release flow works for Capacitor and Expo apps.",{"title":620,"path":621,"stem":622,"children":623,"page":629},"About","\u002Fen\u002Fdocs\u002Fabout","en\u002Fdocs\u002Fabout",[624],{"title":625,"path":626,"stem":627,"description":628},"Security and trust","\u002Fen\u002Fdocs\u002Fabout\u002Fsecurity-trust","en\u002Fdocs\u002Fabout\u002Fsecurity-trust","How Otalan keeps OTA releases controlled: scoped keys, bundle validation, exact matching, rollout controls, rollback, deletion behavior, and support contact.",false,{"title":631,"path":632,"stem":633,"children":634,"page":629},"Build","\u002Fen\u002Fdocs\u002Fbuild","en\u002Fdocs\u002Fbuild",[635],{"title":636,"path":637,"stem":638,"description":639},"Generate a bundle","\u002Fen\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","en\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","Prepare a release artifact that will pass Otalan's validation pipeline, including the extra considerations required for Expo-based publish flows.",{"title":641,"path":642,"stem":643,"children":644,"page":629},"Deploy","\u002Fen\u002Fdocs\u002Fdeploy","en\u002Fdocs\u002Fdeploy",[645],{"title":5,"path":602,"stem":604,"description":598},{"title":647,"path":648,"stem":649,"children":650,"page":629},"Integration","\u002Fen\u002Fdocs\u002Fintegration","en\u002Fdocs\u002Fintegration",[651],{"title":652,"path":653,"stem":654,"description":655},"Migrate from App Center CodePush","\u002Fen\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","en\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","Plan a migration from Microsoft App Center CodePush to Otalan, with mapping notes, rollout guidance, and common failure modes.",{"title":657,"path":658,"stem":659,"children":660,"page":629},"Quick Start","\u002Fen\u002Fdocs\u002Fquick-start","en\u002Fdocs\u002Fquick-start",[661,666,671],{"title":662,"path":663,"stem":664,"description":665},"Capacitor quick start","\u002Fen\u002Fdocs\u002Fquick-start\u002Fcapacitor","en\u002Fdocs\u002Fquick-start\u002Fcapacitor","Wire the Otalan Capacitor runtime into an installed app so it can check for OTA updates, install compatible bundles, and confirm successful launches.",{"title":667,"path":668,"stem":669,"description":670},"Expo quick start","\u002Fen\u002Fdocs\u002Fquick-start\u002Fexpo","en\u002Fdocs\u002Fquick-start\u002Fexpo","Configure expo-updates with Otalan, add the Otalan Expo helper, and make the installed app ready to receive compatible OTA bundles.",{"title":26,"path":672,"stem":673,"description":674},"\u002Fen\u002Fdocs\u002Fquick-start\u002Fquick-start","en\u002Fdocs\u002Fquick-start\u002Fquick-start","Create the first Otalan release path, publish a baseline bundle, verify one update, and prove rollback before widening rollout.",{"title":676,"path":677,"stem":678,"children":679,"page":629},"Tooling","\u002Fen\u002Fdocs\u002Ftooling","en\u002Fdocs\u002Ftooling",[680,685,689],{"title":681,"path":682,"stem":683,"description":684},"AI skill","\u002Fen\u002Fdocs\u002Ftooling\u002Fai-skill","en\u002Fdocs\u002Ftooling\u002Fai-skill","Copy a compact assistant skill for Otalan SDK setup, CLI publishing, and safe credential boundaries.",{"title":31,"path":686,"stem":687,"description":688},"\u002Fen\u002Fdocs\u002Ftooling\u002Fcli","en\u002Fdocs\u002Ftooling\u002Fcli","Learn when to use the Otalan CLI, what workflows it covers, and how it complements the dashboard instead of replacing the platform model.",{"title":690,"path":691,"stem":692,"description":693},"SDKs","\u002Fen\u002Fdocs\u002Ftooling\u002Fsdk","en\u002Fdocs\u002Ftooling\u002Fsdk","Understand the difference between the Capacitor and Expo integrations, and choose the runtime package that matches the way your mobile app actually updates.",{"title":695,"path":696,"stem":697,"children":698,"page":629},"Versions","\u002Fen\u002Fdocs\u002Fversions","en\u002Fdocs\u002Fversions",[699],{"title":700,"path":701,"stem":702,"description":703},"v1","\u002Fen\u002Fdocs\u002Fversions\u002Fv1","en\u002Fdocs\u002Fversions\u002Fv1","Supported runtimes, public limits, and post-v1 candidates for Otalan v1.",1780287525123]