[{"data":1,"prerenderedAt":388},["ShallowReactive",2],{"navigation":3,"page-\u002Fenvironments\u002Fpreview-environments":105,"surround-\u002Fenvironments\u002Fpreview-environments":383},[4,17,25,48,63,74,86],{"title":5,"path":6,"stem":7,"children":8,"icon":16,"exact":11},"Getting started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12],{"title":10,"path":6,"stem":7,"exact":11,"children":-1},"Introduction",true,{"title":13,"path":14,"stem":15,"exact":11,"children":-1},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F2.quickstart","i-lucide-rocket",{"title":18,"path":19,"stem":20,"children":21,"icon":24,"exact":11},"Concepts","\u002Fconcepts","2.concepts\u002F1.index",[22],{"title":23,"path":19,"stem":20,"exact":11,"children":-1},"The Kuppit model","i-lucide-shapes",{"title":26,"path":27,"stem":28,"children":29,"icon":47,"exact":11},"Deployments","\u002Fdeployments","3.deployments\u002F1.index",[30,31,35,39,43],{"title":26,"path":27,"stem":28,"exact":11,"children":-1},{"title":32,"path":33,"stem":34,"exact":11,"children":-1},"Builds","\u002Fdeployments\u002Fbuilds","3.deployments\u002F2.builds",{"title":36,"path":37,"stem":38,"exact":11,"children":-1},"Redeploy and roll back","\u002Fdeployments\u002Fredeploy-and-rollback","3.deployments\u002F3.redeploy-and-rollback",{"title":40,"path":41,"stem":42,"exact":11,"children":-1},"Logs","\u002Fdeployments\u002Flogs","3.deployments\u002F4.logs",{"title":44,"path":45,"stem":46,"exact":11,"children":-1},"When a deployment fails","\u002Fdeployments\u002Fwhen-a-deployment-fails","3.deployments\u002F5.when-a-deployment-fails","i-lucide-cloud-upload",{"title":49,"path":50,"stem":51,"children":52,"icon":62,"exact":11},"Resources","\u002Fresources","4.resources\u002F1.index",[53,54,58],{"title":49,"path":50,"stem":51,"exact":11,"children":-1},{"title":55,"path":56,"stem":57,"exact":11,"children":-1},"Web services","\u002Fresources\u002Fweb-services","4.resources\u002F2.web-services",{"title":59,"path":60,"stem":61,"exact":11,"children":-1},"PostgreSQL","\u002Fresources\u002Fpostgresql","4.resources\u002F3.postgresql","i-lucide-boxes",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":73,"exact":11},"Configuration","i-lucide-sliders-horizontal","\u002Fconfiguration","5.configuration",[69],{"title":70,"path":71,"stem":72,"exact":11,"children":-1},"Environment variables","\u002Fconfiguration\u002Fvariables","5.configuration\u002F1.variables",false,{"title":75,"path":76,"stem":77,"children":78,"icon":85,"exact":11},"Domains","\u002Fdomains","7.domains\u002F1.index",[79,81],{"title":80,"path":76,"stem":77,"exact":11,"children":-1},"Hostnames",{"title":82,"path":83,"stem":84,"exact":11,"children":-1},"Custom domains","\u002Fdomains\u002Fcustom-domains","7.domains\u002F2.custom-domains","i-lucide-globe",{"title":87,"path":88,"stem":89,"children":90,"icon":104,"exact":11},"Environments","\u002Fenvironments","8.environments\u002F1.index",[91,92,96,100],{"title":87,"path":88,"stem":89,"exact":11,"children":-1},{"title":93,"path":94,"stem":95,"exact":11,"children":-1},"Preview environments","\u002Fenvironments\u002Fpreview-environments","8.environments\u002F2.preview-environments",{"title":97,"path":98,"stem":99,"exact":11,"children":-1},"Named environments","\u002Fenvironments\u002Fnamed-environments","8.environments\u002F3.named-environments",{"title":101,"path":102,"stem":103,"exact":11,"children":-1},"Deleting an environment","\u002Fenvironments\u002Fdeleting-an-environment","8.environments\u002F4.deleting-an-environment","i-lucide-git-branch",{"id":106,"title":93,"badge":107,"body":108,"category":107,"description":377,"draft":73,"extension":378,"links":107,"meta":379,"navigation":11,"path":94,"seo":380,"sitemap":381,"stem":95,"__hash__":382},"docs\u002F8.environments\u002F2.preview-environments.md",null,{"type":109,"value":110,"toc":366},"minimark",[111,115,120,123,152,164,168,179,189,196,200,207,278,285,289,292,316,319,323,329,343,346,350,353,356,360],[112,113,114],"p",{},"A preview environment is a copy of your Production service, deployed from a pull request's branch on a hostname of its own. Kuppit creates it when the pull request opens, redeploys it on every push, and removes it when the pull request closes. Nothing about it is configured by hand.",[116,117,119],"h2",{"id":118},"what-a-preview-contains","What a preview contains",[112,121,122],{},"A preview is deliberately smaller than Production:",[124,125,126,134,146],"ul",{},[127,128,129,133],"li",{},[130,131,132],"strong",{},"One web service",", copied from Production: the same name, the same build settings, the same Dockerfile path, deploying the pull request's head branch.",[127,135,136,139,140,145],{},[130,137,138],{},"No database."," Previews are created from pull requests and are meant to be disposable, and copying production data into every pull request is the accident this rule prevents. A service in a preview that references a database therefore has nothing to reference; see ",[141,142,144],"a",{"href":143},"#variables-in-a-preview","variables"," below.",[127,147,148,151],{},[130,149,150],{},"Nothing else."," Every other component of the project is recorded as deliberately absent, and a resource cannot be added to a preview from the dashboard.",[112,153,154,155,159,160,163],{},"The preview is named after the pull request, ",[156,157,158],"code",{},"PR #42",", and appears in the environment selector as ",[156,161,162],{},"#42 · \u003Cbranch>"," while it exists.",[116,165,167],{"id":166},"hostname","Hostname",[112,169,170,171,174,175,178],{},"A preview's hostname is Production's hostname with the environment's slug in front. For a project named ",[156,172,173],{},"acme"," whose service is ",[156,176,177],{},"web",":",[180,181,187],"pre",{"className":182,"code":184,"language":185,"meta":186},[183],"language-text","acme-a1b2c3.kuppit.app          Production\npr-42-acme-a1b2c3.kuppit.app    PR #42\n","text","",[156,188,184],{"__ignoreMap":186},[112,190,191,192,195],{},"The ",[156,193,194],{},"pr-\u003Cnumber>-"," prefix is reserved, so a project name can never collide with a preview. The hostname is kept when the pull request closes, and a reopened pull request comes back on the same URL.",[116,197,199],{"id":198},"the-check-on-the-pull-request","The check on the pull request",[112,201,202,203,206],{},"Kuppit reports through a GitHub check run named ",[130,204,205],{},"Kuppit Preview"," on the pull request's commit, updated in place as the deployment moves. It never posts a comment.",[208,209,210,226],"table",{},[211,212,213],"thead",{},[214,215,216,220,223],"tr",{},[217,218,219],"th",{},"State",[217,221,222],{},"Title",[217,224,225],{},"Summary",[227,228,229,241,256,267],"tbody",{},[214,230,231,235,238],{},[232,233,234],"td",{},"In progress",[232,236,237],{},"Deploying…",[232,239,240],{},"Kuppit is building and deploying this pull request.",[214,242,243,246,249],{},[232,244,245],{},"Success",[232,247,248],{},"Deployed",[232,250,251,252,255],{},"The preview for this pull request is live at ",[156,253,254],{},"https:\u002F\u002Fpr-42-….kuppit.app",".",[214,257,258,261,264],{},[232,259,260],{},"Failure",[232,262,263],{},"Build failed, or Deployment failed",[232,265,266],{},"Which phase failed. Open the deployment in Kuppit for the logs.",[214,268,269,272,275],{},[232,270,271],{},"Refused",[232,273,274],{},"No preview",[232,276,277],{},"Why no preview was created, for example that previews are turned off for the project.",[112,279,280,281,284],{},"The check needs the GitHub App's ",[130,282,283],{},"Checks: write"," permission. Without it, previews still deploy; only the check is missing.",[116,286,288],{"id":287},"variables-in-a-preview","Variables in a preview",[112,290,291],{},"When a preview is created, or a closed pull request is reopened, Kuppit copies the service's variables from Production:",[124,293,294,300,310],{},[127,295,296,299],{},[130,297,298],{},"Non-secret literals"," are always copied.",[127,301,302,305,306,309],{},[130,303,304],{},"Secrets"," are not, unless the project's ",[130,307,308],{},"Give previews the production secrets"," setting is on. Code in an open pull request can read anything the preview receives, which is why the default is off.",[127,311,312,315],{},[130,313,314],{},"References"," are dropped, because a reference can only target a resource in the same environment and a preview has no database.",[112,317,318],{},"The copy happens once, at creation. A variable changed in Production afterwards does not change the preview, and a variable set directly on the preview's service survives every later push. Turning the secrets setting on applies to previews created or reopened afterwards, never to one already running.",[116,320,322],{"id":321},"settings","Settings",[112,324,325,326,328],{},"The project's ",[130,327,322],{}," has two switches:",[124,330,331,337],{},[127,332,333,336],{},[130,334,335],{},"Create previews for pull requests."," On by default. Every pull request gets its own environment and its own URL, cleaned up when the pull request closes.",[127,338,339,342],{},[130,340,341],{},"Give previews the production secrets."," Off by default, as above.",[112,344,345],{},"Pull requests from forks never get a preview, whatever the settings say. The check on the pull request says so.",[116,347,349],{"id":348},"when-the-pull-request-closes","When the pull request closes",[112,351,352],{},"Closing or merging the pull request removes the preview immediately: routing is withdrawn first, then the service and its images are destroyed, and the environment disappears from the selector. The cleanup runs even if previews have since been turned off, and a push to the branch after the close does not bring the preview back. Only reopening the pull request does.",[112,354,355],{},"Deployment history and the hostname are kept. Kuppit learns about a close from GitHub's delivery, so a pull request closed while the GitHub App was uninstalled is not discovered later.",[116,357,359],{"id":358},"limits","Limits",[112,361,362,363,365],{},"Each plan allows a number of preview environments to exist at once in a project. A pull request opened beyond that number gets a ",[130,364,274],{}," check saying so. Only a preview that does not already exist counts, so a push to an open pull request is never refused. The numbers are provisional during the alpha.",{"title":186,"searchDepth":367,"depth":367,"links":368},3,[369,371,372,373,374,375,376],{"id":118,"depth":370,"text":119},2,{"id":166,"depth":370,"text":167},{"id":198,"depth":370,"text":199},{"id":287,"depth":370,"text":288},{"id":321,"depth":370,"text":322},{"id":348,"depth":370,"text":349},{"id":358,"depth":370,"text":359},"Every pull request gets its own environment and URL, updated on each push and removed when the pull request closes.","md",{},{"title":93,"description":377},{"loc":94},"AyH86vRXlOFvNvJSTtbH9jf3srdhDU_cMKLfDTdtHI8",[384,386],{"title":87,"path":88,"stem":89,"description":385,"children":-1},"Production, preview and named environments, what each one contains, and how they stay isolated from each other.",{"title":97,"path":98,"stem":99,"description":387,"children":-1},"Create a long-lived environment such as staging from an existing one, deciding per resource whether it gets its own copy, shares, clones or does without.",1788534986857]